Im trying to catch an error when uploading a file that is too large.
At the server, the multipart section reader throws which I catch and return as an BadRequest (also tried InternalError) :
try
{
var section = await reader.ReadNextSectionAsync();
while (section != null)
{
...
}
}
catch (Exception ex)
{
return StatusCode((int)HttpStatusCode.BadRequest, ProblemFactory.Shared.BadRequestProblem("Could not upload file", ex.Message));
}
To upload, I have the following (using RestSharp currently, but same result with HttpClient via HttpClientFactory):
var request = new RestRequest(REQ_UPLOADFILE, Method.POST, DataFormat.Json);
var token = await _agentTokenService.GetToken();
AddTokenHeader(request, token.AccessToken);
request.AddFile("file", path);
request.AddParameter("externalFileType", fileType, ParameterType.GetOrPost);
request.AddParameter("subType", subType, ParameterType.GetOrPost);
var resp = await _client.ExecuteTaskAsync(request);
if (resp.IsSuccessful)
{
return JsonConvert.DeserializeObject<ExternalFileResponse>(resp.Content);
}
else
{
string reason = "unknown error";
//switch(resp.StatusCode)
//{
// case HttpStatusCode.???
//}
throw new Exception($"Could not upload file: {reason}");
}
The response from the post is status code 0 with a message:
The stream does not support concurrent IO read or write operations
The upload is running in a task so I guess it's something to do with that, but there is only a single download running and if the file is smaller it works without a problem.
I can only think that something in the response handling is fracking with this somehow.
Does anyone have a clue??
Thanks and Merry Christmas :)
PS: Im using Kestrel only - no IIS or nginx - with options thus:
.UseKestrel(options =>
{
options.AddServerHeader = false;
options.Limits.MaxRequestBodySize = 100 * 1024 * 1024; // 100 MB
})
UPDATE
I think I understand this better now.
The server is terminating the connection when reading the bytes form the stream.
The client, writing asyncly, continues for a little bit, but I then try to read the response - hence the error message.
UPDATE
HttpClient does actually respond a little differently - I get my badrequest and the message is that the stream was closed.
here is a simple way to loading large file use ASP.NET.
(1)downloand webupload from https://github.com/fex-team/webuploader
(2) webupload can upload large file to chunk file,crate a webform
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="../Javascript/jquery-1.9.1.min.js"></script>
<link href="../javascript/webuploader/webuploader.css" rel="stylesheet" />
<script src="../javascript/webuploader/webuploader.js"></script>
</head>
<body >
<form>
<br /><br />
<div id="uploader" class="wu-example">
<div class="btns">
<div id="picker" style="display:inline-block">Select a File</div>
<input id="ctlBtn" type="button" value="Upload" class="btn btn-primary" style="border-radius:0px; position:relative; top:-13px"/>
</div>
<div id="thelist" class="uploader-list"></div>
</div>
<script>
_extensions = '3gp,mp4,rmvb,mov,avi,m4v';
_mimeTypes = 'video/*,audio/*,application/*';
var GUID = WebUploader.Base.guid();//一个GUID
// alert(GUID);
uploader = WebUploader.create({
auto: false,
// swf path
swf: '../javascript/webuploader/Uploader.swf',
//server receive data
server: '_uploadVideo.aspx',
pick: {
id: '#picker',
label: 'Select a File',
innerHTML: 'Select a File',
multiple: false
},
fileNumLimit: 1,
fileSingleSizeLimit: 1024 * 1024 * 120,
accept: {
title: 'large file',
extensions: _extensions,
mimeTypes: _mimeTypes, // eg. image/*,
},
chunked: true,//split large into small file
chunkSize: 1024 * 1024 * 2, //every small file size,this is 2M
formData: {
guid: GUID,
types:"upload"
}
});
uploader.on('fileQueued', function (file) {
$("#thelist").append('<div id="' + file.id + '" class="item">' +
'<b class="info">' + file.name + '</b> ' +
'<p class="state">wait...</p>' + '</div>');
});
uploader.on('uploadSuccess', function (file, response) {
//merge small into a large file
$('#' + file.id).find('p.state').html('<font color=green>upload success</font>');
$.post('_uploadVideo.aspx', { guid: GUID, fileName: file.name, types: "merge" ,r:Math.random(),itemid:<%=Request.QueryString["itemid"]%> },
function (data) {
if (data == 1) {
alert("success");
}
else {
alert("fail");
}
});
});
uploader.on("error", function (type, handler) {
if (type == "Q_TYPE_DENIED") {
alert("format error");
} else if (type == "F_EXCEED_SIZE") {
alert("size too large");
}
});
uploader.on('uploadProgress', function (file, percentage) {
var $li = $('#' + file.id),
$percent = $li.find('.progress .progress-bar');
// stop re-upload
if (!$percent.length) {
$percent = $('<div class="progress progress-striped active">' +
'<div class="progress-bar" role="progressbar" style="width: 0%">' +
'</div>' +
'</div>').appendTo($li).find('.progress-bar');
}
$li.find('p.state').text('uploading');
$percent.css('width', percentage * 100 + '%');
});
$("#ctlBtn").click(
function () {
uploader.upload();
}
);
</script>
</form>
</body>
</html>
(3)create a asp.net webform page _uploadVideo.aspx
delete all content,the aspx should only has 1 line
<%# Page Language="C#" AutoEventWireup="true" CodeFile="_uploadVideo.aspx.cs" Inherits="Gallery.Gallery._uploadVideo" %>
(4)in code _uploadVideo.aspx.cs wirte code below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Data.SqlClient;
namespace Gallery.Gallery
{
public partial class _uploadVideo : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Request["types"] == "upload")
{
if (Request.Form.AllKeys.Any(m => m == "chunk"))
{
int year = DateTime.Now.Year;
//取得chunk和chunks
int chunk = Convert.ToInt32(Request["chunk"]);
int chunks = Convert.ToInt32(Request["chunks"]);
string folder = Server.MapPath("../uploads/video/"+year+"/" + Request["guid"] + "/");
string path = folder + chunk;
//建立临时传输文件夹 create teamplate folder
if (!Directory.Exists(Path.GetDirectoryName(folder)))
{
Directory.CreateDirectory(folder);
}
FileStream addFile = new FileStream(path, FileMode.Append, FileAccess.Write);
BinaryWriter AddWriter = new BinaryWriter(addFile);
//获得上传的分片数据流 get chunk
var file = Request.Files[0];
Stream stream = file.InputStream;
BinaryReader TempReader = new BinaryReader(stream);
//将上传的分片追加到临时文件末尾
AddWriter.Write(TempReader.ReadBytes((int)stream.Length));
//关闭BinaryReader文件阅读器
TempReader.Close();
stream.Close();
AddWriter.Close();
addFile.Close();
TempReader.Dispose();
stream.Dispose();
AddWriter.Dispose();
addFile.Dispose();
string f_ext = Path.GetExtension(file.FileName);
string _result = "{\"chunked\" :\"true\",\"hasError\" :\"false\",\"f_ext\" :\"" + f_ext + "\" }";
System.Web.HttpContext.Current.Response.Write(_result);
}
}
if (Request["types"] == "merge")
{
try
{
int year = DateTime.Now.Year;
var guid = Request["guid"];//GUID
var uploadDir = Server.MapPath("../uploads/video/" + year+"/");//Upload 文件夹
//建立临时传输文件夹
if (!Directory.Exists(Path.GetDirectoryName(uploadDir)))
{
Directory.CreateDirectory(uploadDir);
}
var dir = Path.Combine(uploadDir, guid);//临时文件夹
var ext = Path.GetExtension(Request["fileName"]);
var files = Directory.GetFiles(dir);//获得下面的所有文件
var name = Guid.NewGuid().ToString("N") + ext;
var finalPath = Path.Combine(uploadDir, name);//最终的文件名
var fs = new FileStream(finalPath, FileMode.Create);
foreach (var part in files.OrderBy(x => x.Length).ThenBy(x => x))//排一下序,保证从0-N Write
{
var bytes = System.IO.File.ReadAllBytes(part);
fs.Write(bytes, 0, bytes.Length);
bytes = null;
System.IO.File.Delete(part);//删除分块
}
fs.Flush();
fs.Close();
Directory.Delete(dir);//删除文件夹
//INSERT INTO DB finalPath
SqlParameter[] p = {
new SqlParameter("#videopath","../uploads/video/" + year+"/"+name)
};
string sql = #"update portal_photoes set videopath=#videopath where id=" + int.Parse(Request["itemid"]);
//you can exe SQL to into database
System.Web.HttpContext.Current.Response.Write("1");
}
catch (Exception ex)
{
System.Web.HttpContext.Current.Response.Write("0");
}
}
}
}
}
Related
I am developing an application where I have to get the data from an Excel sheet and use it in the application, but I am having trouble accessing the data. Should I use Entity Framework and move the Data to a database or do I just import the data from Excel and use it?
Not sure what trouble you are meeting to access the data. But here is a sample about importing Excel data to Asp.net core application, you could refer to it.
In this sample, it will upload the excel file to the wwwroot folder using JavaScript first, then, using the DotNetCore.NPOI package (open source, you could install it via Nuget) to extract the data from excel. Details steps as below:
Suppose there have a testdata.xlsx file, the content as below:
Code in the controller:
private readonly IWebHostEnvironment _hostEnvironment;
public HomeController(ILogger<HomeController> logger, IWebHostEnvironment environment)
{
_logger = logger;
_hostEnvironment = environment;
}
public IActionResult Upload()
{
return View();
}
[HttpPost]
public IActionResult Import()
{
IFormFile file = Request.Form.Files[0];
string folderName = "UploadExcel";
string webRootPath = _hostEnvironment.WebRootPath;
string newPath = Path.Combine(webRootPath, folderName);
StringBuilder sb = new StringBuilder();
if (!Directory.Exists(newPath))
{
Directory.CreateDirectory(newPath);
}
if (file.Length > 0)
{
string sFileExtension = Path.GetExtension(file.FileName).ToLower();
ISheet sheet;
string fullPath = Path.Combine(newPath, file.FileName);
using (var stream = new FileStream(fullPath, FileMode.Create))
{
file.CopyTo(stream);
stream.Position = 0;
if (sFileExtension == ".xls")
{
HSSFWorkbook hssfwb = new HSSFWorkbook(stream); //This will read the Excel 97-2000 formats
sheet = hssfwb.GetSheetAt(0); //get first sheet from workbook
}
else
{
XSSFWorkbook hssfwb = new XSSFWorkbook(stream); //This will read 2007 Excel format
sheet = hssfwb.GetSheetAt(0); //get first sheet from workbook
}
IRow headerRow = sheet.GetRow(0); //Get Header Row
int cellCount = headerRow.LastCellNum;
sb.Append("<table class='table table-bordered'><tr>");
for (int j = 0; j < cellCount; j++)
{
NPOI.SS.UserModel.ICell cell = headerRow.GetCell(j);
if (cell == null || string.IsNullOrWhiteSpace(cell.ToString())) continue;
sb.Append("<th>" + cell.ToString() + "</th>");
}
sb.Append("</tr>");
sb.AppendLine("<tr>");
var emplist = new List<EmployeeViewModel>();
for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++) //Read Excel File
{
IRow row = sheet.GetRow(i);
if (row == null) continue;
if (row.Cells.All(d => d.CellType == CellType.Blank)) continue;
for (int j = row.FirstCellNum; j < cellCount; j++)
{
if (row.GetCell(j) != null)
sb.Append("<td>" + row.GetCell(j).ToString() + "</td>");
}
sb.AppendLine("</tr>");
EmployeeViewModel emp = new EmployeeViewModel() {
EmployeeID = Convert.ToInt32(row.Cells[0].ToString()),
EmployeeName = row.Cells[1].ToString(),
Age = Convert.ToInt32(row.Cells[2].ToString()),
Sex = row.Cells[3].ToString(),
Designation = row.Cells[4].ToString()
};
emplist.Add(emp);
}
var result = emplist;
sb.Append("</table>");
}
}
return this.Content(sb.ToString());
//return View("Upload");
}
Code in the Upload view:
<form asp-controller="Home" asp-action="Export">
<div class="container">
<div class="row">
<div class="col-md-4">
<input type="file" id="fileupload" name="files" class="form-control" />
</div>
<div class="col-md-3">
<input type="button" name="Upload" value="Upload" id="btnupload" class="btn btn-primary" />
Download
</div>
<div class="col-md-5">
<input type="submit" name="Export" value="Create and Export" id="btnExport"
class="btn btn-primary" asp-action="Export" />
</div>
</div>
<div class="clearfix"> </div>
<div class="row">
<div id="divPrint"></div>
</div>
</div>
</form>
And the Java Script code:
<script type="text/javascript">
$(function () {
$('#btnupload').on('click', function () {
var fileExtension = ['xls', 'xlsx'];
var filename = $('#fileupload').val();
if (filename.length == 0) {
alert("Please select a file.");
return false;
}
else {
var extension = filename.replace(/^.*\./, '');
if ($.inArray(extension, fileExtension) == -1) {
alert("Please select only excel files.");
return false;
}
}
var fdata = new FormData();
var fileUpload = $("#fileupload").get(0);
var files = fileUpload.files;
fdata.append(files[0].name, files[0]);
$.ajax({
type: "POST",
url: "/Home/Import",
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
data: fdata,
contentType: false,
processData: false,
success: function (response) {
if (response.length == 0)
alert('Some error occured while uploading');
else {
$('#divPrint').html(response);
}
},
error: function (e) {
$('#divPrint').html(e.responseText);
}
});
})
$('#btnExport').on('click', function () {
var fileExtension = ['xls', 'xlsx'];
var filename = $('#fileupload').val();
if (filename.length == 0) {
alert("Please select a file then Import");
return false;
}
});
});
</script>
The result like this:
You could also create a Employee model to store the data:
public class EmployeeViewModel
{
public int EmployeeID { get; set; }
public string EmployeeName { get; set; }
public int Age { get; set; }
public string Sex { get; set; }
public string Designation { get; set; }
}
Then, when loop through the excel rows, use the following code to get the Employee List:
var emplist = new List<EmployeeViewModel>();
for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++) //Read Excel File
{
IRow row = sheet.GetRow(i);
if (row == null) continue;
if (row.Cells.All(d => d.CellType == CellType.Blank)) continue;
for (int j = row.FirstCellNum; j < cellCount; j++)
{
if (row.GetCell(j) != null)
sb.Append("<td>" + row.GetCell(j).ToString() + "</td>");
}
sb.AppendLine("</tr>");
EmployeeViewModel emp = new EmployeeViewModel() {
EmployeeID = Convert.ToInt32(row.Cells[0].ToString()),
EmployeeName = row.Cells[1].ToString(),
Age = Convert.ToInt32(row.Cells[2].ToString()),
Sex = row.Cells[3].ToString(),
Designation = row.Cells[4].ToString()
};
emplist.Add(emp);
}
If the above sample doesn't achieve your requirement, please explain more details about what trouble are you having and what library you are using to upload the excel.
Reference:
Import and Export Excel file using NPOI
Import (Insert) Excel file data into Database ASP.Net Core MVC (using OLEDB library)
Getting HTML DOM from websites that work with client-side (JavaScript)
It doesn't work because
<div class="currTableContainer" id="divCurrTableContainer">
is empty. There is nothing in it. You wont find a table in it. Hence the nullpointer. The HTML you're looking for is generated by a script(ajax).
Check the loaded HTML to confirm.
Because I was bored I decided to finish your homework. You can't use HAP in this case. You have to use the ajax service they provided. Also better since the data is prone to change a lot. The code that is used on the site(ajax script) looks like this:
$("document").ready(function () {
$.ajax({
type: "POST",
url: '/_layouts/15/LINKDev.CIB.CurrenciesFunds/FundsCurrencies.aspx/GetCurrencies',
async: true,
data: "{'lang':'" + document.getElementById("ctl00_ctl48_g_5d7fc52f_a66d_4aa2_8d6c_c01fb4b38cb2_hdnLang").value + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
if (msg.d != null && msg.d.length > 0) {
var contentHTML = "<table class='currTable' cellspacing='0' rules='all' style='border-width:0px;border-collapse:collapse;'>"
+ "<tbody><tr class='currHeaderRow'>"
+ "<th scope='col'>" + document.getElementById("ctl00_ctl48_g_5d7fc52f_a66d_4aa2_8d6c_c01fb4b38cb2_hdnCurrency").value + "</th><th scope='col'>" + document.getElementById("ctl00_ctl48_g_5d7fc52f_a66d_4aa2_8d6c_c01fb4b38cb2_hdnBuy").value + "</th><th scope='col'>" + document.getElementById("ctl00_ctl48_g_5d7fc52f_a66d_4aa2_8d6c_c01fb4b38cb2_hdnSell").value + "</th>"
+ "</tr>";
for (var i = 0; i < msg.d.length; i++) {
if (msg.d[i].CurrencyID.length > 0) {
contentHTML += "<tr class='currRow'>"
+ "<td>" + msg.d[i].CurrencyID + "</td><td>" + msg.d[i].BuyRate + "</td><td class='lastCell'>" + msg.d[i].SellRate + "</td>"
+ "</tr>";
}
}
contentHTML += "</tbody></table>";
$("#divCurrTableContainer").html(contentHTML);
if ($(".bannerElements").length > 0)
FixCurrenciesRatesScroll();
}
},
error: function (msg) {
}
});
});
As you can see the script uses an URL from a different part of the site to update their currency. In order to fetch it you just make http request with the following JSON {"lang":"en"}. I have translated the script into it's equivalent in C# below. The response from the http request will be JSON formatted. Which means you will have to create a class that can be used to serialize the data. I recommend you look at Newtonsoft for this since I can't do all your homework.
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net;
namespace test
{
class Program
{
public static void Main(string[] args)
{
try
{
string webAddr = "http://www.cibeg.com/_layouts/15/LINKDev.CIB.CurrenciesFunds/FundsCurrencies.aspx/GetCurrencies";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(webAddr);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
httpWebRequest.Expect = "application/json";
string datastring = "{\"lang\":\"en\"}";
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] data = encoder.GetBytes(datastring);
httpWebRequest.ContentLength = data.Length;
httpWebRequest.GetRequestStream().Write(data, 0, data.Length);
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
Console.WriteLine(responseText);
//Now you have your response.
//or false depending on information in the response
}
}
catch (WebException ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
}
<cc1:AjaxFileUpload ID="AjaxFileUpload1" AllowedFileTypes="jpg,jpeg"
runat="server" MaximumNumberOfFiles="4" OnUploadComplete="AjaxFileUpload1_UploadComplete"
/>
Code behind file
protected void AjaxFileUpload1_UploadComplete(object sender, AjaxControlToolkit.AjaxFileUploadEventArgs e)
{
if (e.FileSize > 10)
{
string filePath = e.FileName;
AjaxFileUpload1.SaveAs(Server.MapPath(filePath));
}
else
{
}
}
I want to check that all the files size should not exceed a particular value before the files upload event.
Try this way:
Server side:
protected void AjaxFileUpload1_UploadComplete(object sender, AjaxControlToolkit.AjaxFileUploadEventArgs e)
{
try
{
string savePath = MapPath("~/Images/" + e.FileName);
// dont save file & return if condition not matched.
if (e.FileSize > 72000) // use same condition in client side code
{
return;
}
AjaxFileUpload1.SaveAs(savePath);
}
catch (Exception ex)
{
throw ex;
}
}
and on client side:
<script type="text/javascript">
function UploadComplete(sender, args) {
var filesize = args.get_fileSize();
var fileId = args.get_fileId();
var status = document.getElementById('AjaxFileUpload1_FileItemStatus_' + fileId);
var container = document.getElementById('AjaxFileUpload1_FileInfoContainer_' + fileId);
if (filesize > 72000) { // same condition used for server side
document.getElementById('lblStatus').innerText = "error";
if (status.innerText) {
status.innerText = " (Error)";
}
if (status.textContent) {
status.textContent = " (Error)";
}
container.style.color = 'Red';
}
}
</script>
<cc1:AjaxFileUpload ID="AjaxFileUpload1" AllowedFileTypes="jpg,jpeg" runat="server" MaximumNumberOfFiles="4" OnUploadComplete="AjaxFileUpload1_UploadComplete" OnClientUploadComplete="UploadComplete" />
Hope this helps!!
<script type="text/javascript">
$(".ajax__fileupload_dropzone").bind("drop", function () {
checkfilesize();
});
$(".ajax__fileupload_queueContainer").bind("click", function () {
checkfilesize();
});
$(".ajax__fileupload_uploadbutton").bind("mouseenter", function () {
checkfilesize();
});
function checkfilesize() {
var total_filesize_num = 0;
var myElements = $(".filesize");
if (myElements.length == 0) {
$(".ajax__fileupload_uploadbutton").css("visibility", "hidden");
return;
}
for (var i = 0; i < myElements.length; i++) {
var filesize = myElements.eq(i).html(); //$(".filesize").html();
total_filesize_num = total_filesize_num + filesize_tonum(filesize);
}
if (total_filesize_num > 5) {
$(".ajax__fileupload_uploadbutton").css("visibility", "hidden");
alert('Maximum file size is 5MB only! Please select another one.');
return;
} else {
$(".ajax__fileupload_uploadbutton").css("visibility", "visible");
}
}
function countsumfilesize() {
var sumfilesize = 0;
var myElements = $(".filesize");
for (var i = 0; i < myElements.length; i++) {
alert(myElements.eq(i).html());
}
}
function filesize_tonum(filesize) {
var filesize_num = 0;
if (filesize.indexOf("kb") > 0) {
var space = filesize.lastIndexOf(" ");
filesize_num = parseFloat("0." + filesize.substr(0, filesize.length - space + 1));
}
else if (filesize.indexOf("MB") > 0) {
var space = filesize.lastIndexOf(" ");
filesize_num = parseFloat(filesize.substr(0, filesize.length - space + 1));
}
return filesize_num;
}
</script>
<ajaxToolkit:AjaxFileUpload ID="AjaxFileUploadImage" runat="server" OnClientUploadComplete="uploadComplete" MaximumNumberOfFiles="1" AllowedFileTypes="gif,png,jpg,jpeg" onchange="checkfilesize(); return false;" />
See the code below:
public void afuUpload_UploadedComplete(object sender, AsyncFileUploadEventArgs e)
{
try
{
string savePath = MapPath("~/Uploads/" + Path.GetFileName(e.filename));
if (int.Parse(e.filesize) > 3000000)
{
return;
}
afuUpload.SaveAs(savePath);
}
catch (Exception ex)
{
throw ex;
}}
The idea is to prevent the file is uploaded to the server. In the proposed solution, when the flow code has reached afuUpload_UploadedComplete, the file was uploaded to server, but has not yet been recorded in the path you specify. For example, if the limit is 20 megabytes and the selected file is 22 megabytes, when the code reaches afuUpload_UploadedComplete, 22 Megabytes already been uploaded to the server.
The solution sought is that the validation is done on the client side (JavaScript) and that prevents the code arrives to CodeBehind on the server.
In my case, I tried to OnClientUploadComplete generating an exception when the file size limit is exceeded, but it did not work and the code is still reaching the CodeBehind. The other problem is that when the exception occurs, the JavaScript function OnClientUploadError is not firing to intercept the exception generated in OnClientUploadComplete function.
Controller
[HttpPost]
public ActionResult Create(string Album, Photo photo, IEnumerable<HttpPostedFileBase> files, DateTime? datec, string NewAlbum = null)
{
.....
foreach (var file in files)
{
decimal sum = file.ContentLength / 1048;
if (sum > 4000)
{
errorlist2 += "Sorry " + file.FileName + " has exceeded its file limit off 4 MB <br/>";
}
}
if (errorlist2 != "")
{
ViewBag.Error = errorlist2;
return View(photo);
}
// we dont want put the message in the loop it will come out on first max limit , rather find all files in excess, then we can pass the message
//also make sure your web config is set for a limit on max size
//using the normal html multi uploaded
// <input type="file" name="files" id="files" required multiple="multiple" accept=".jpg, .png, .gif" size="4" />
I am trying to create an iOS app using PhoneGap that will allow a user to upload photos to a web server. Here is my code.
<!DOCTYPE html>
<html>
<head>
<title>Capture Photo</title>
<script type="text/javascript" charset="utf-8" src="cordova-1.9.0.js"></script>
<script type="text/javascript" charset="utf-8">
// Wait for PhoneGap to load
document.addEventListener("deviceready", onDeviceReady, false);
// PhoneGap is ready
function onDeviceReady() {
// Do cool things here...
}
function getImage() {
// Retrieve image file location from specified source
navigator.camera.getPicture(uploadPhoto, function(message) {
alert('get picture failed');
},{
quality: 50,
destinationType: navigator.camera.DestinationType.FILE_URI,
sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY
}
);
}
function uploadPhoto(imageURI) {
var options = new FileUploadOptions();
options.fileKey="recFile";
options.fileName=imageURI.substr(imageURI.lastIndexOf('/')+1);
options.mimeType="image/jpeg";
var params = new Object();
params.value1 = "test";
params.value2 = "param";
options.params = params;
var ft = new FileTransfer();
ft.upload(imageURI, "http://someWebSite.com/Testing/SaveImage.asmx/SaveImage", win, fail, options, true);
}
function win(r) {
console.log("Code = " + r.responseCode);
console.log("Response = " + r.response);
console.log("Sent = " + r.bytesSent);
}
function fail(error) {
alert("An error has occurred: Code = " + error.code);
alert("source = " + error.source);
alert("http_status = " + error.http_status);
console.log("upload error source " + error.source);
console.log("upload error target " + error.target);
}
</script>
</head>
<body>
<button onclick="getImage();">Upload a Photo</button>
</body>
Is anything wrong with my index.html file, or is the problem with the ASMX file?
Whenever I try to test this out on a 4th generation iPod Touch, I get the following error message:
2012-07-09 16:24:03.257 Test1[916:707] File Transfer Finished with response code 404
2012-07-09 16:24:03.260 Test1[916:707] FileTransferError {
code = 3;
"http_status" = 404;
source = "http://someWebSite.com/Testing/SaveImage.asmx/SaveImage";
target = "file://localhost/var/mobile/Applications/5DD01E68-02F7-410B-996A- 2D70BF1A61D3/tmp/cdv_photo_046.jpg";}
2012-07-09 16:24:07.137 Test1[916:707] ERROR: Plugin 'Debug Console' not found, or is not a CDVPlugin. Check your plugin mapping in Cordova.plist.
You can follow this example Upload image from android phonegap to a server using asmx
Or
A simple example
the js
<!DOCTYPE HTML>
<html>
<head>
<title>Cordova</title>
<link rel="stylesheet" href="style.css" media="screen" />
<script type="text/javascript" charset="utf-8" src="cordova-2.0.0.js"></script>
<script type="text/javascript" charset="utf-8" src="jquery-1.7.2.min.js"></script>
<script type="text/javascript" charset="utf-8">
var pictureSource; // picture source
var destinationType; // sets the format of returned value
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
pictureSource = navigator.camera.PictureSourceType;
destinationType = navigator.camera.DestinationType;
}
</script>
</head>
<body>
<script type="text/javascript" charset="utf-8">
var myData = "";
$(document).ready(function() {
$("#getDataFromServer").click(function() {
var imageData = myData;
$.ajax({
type : "POST",
url : 'http://my.domain.name/saveImage.ashx',
data : {
image : imageData
},
beforeSend : function() {
$("#comment2").text("Start ajax " + imageData.length);
},
success : function(data) {
$("#comment2").text("Uploaded! " + data);
},
error : function(request, error) {
$("#comment2").text("Error! " + error);
}
});
});
})
function capturePhotoEdit(source) {
navigator.camera.getPicture(onPhotoDataSuccess, onFail, {
quality : 50,
destinationType : destinationType.DATA_URL,
sourceType : source
});
}
function onFail(message) {
alert('Failed because: ' + message);
}
function onPhotoDataSuccess(imageData) {
console.log(imageData);
var smallImage = document.getElementById('smallImage');
smallImage.style.display = 'block';
smallImage.src = "data:image/jpeg;base64," + imageData;
myData = imageData;
$("#comment").text(imageData.length);
}
</script>
<h1>Hello World</h1>
<p>
<a href="#" onclick="capturePhotoEdit(pictureSource.PHOTOLIBRARY);">get
image</a>
</p>
<p>
send image
</p>
<span id="comment2"></span>
<img style="display: none; width: 100px; height: 100px;"
id="smallImage" src="" />
<span id="imagename"></span>
<span id="comment"></span>
the asp.net handler saveImage.ashx
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Text;
namespace Recepies
{
/// <summary>
/// Summary description for saveImage
/// </summary>
public class saveImage : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
try
{
string filePath = "";
filePath = context.Server.MapPath(".");
string fileName = RandomString(10);
string myImage = context.Request.Form["image"];
if (myImage.Length > 0)
{
File.WriteAllBytes(filePath + "/upload/" + fileName + ".jpg", Convert.FromBase64String(myImage));
context.Response.ContentType = "text/plain";
context.Response.Write("File was saved - " + fileName + ".jpg");
}
else
{
context.Response.ContentType = "text/plain";
context.Response.Write("File was not saved");
}
}
catch (Exception ex)
{
context.Response.ContentType = "text/plain";
context.Response.Write(ex.Message);
}
}
private static Random random = new Random((int)DateTime.Now.Ticks);//thanks to McAden
private string RandomString(int size)
{
StringBuilder builder = new StringBuilder();
char ch;
for (int i = 0; i < size; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
builder.Append(ch);
}
return builder.ToString();
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
I've been having the same issue (on iOS7). The solution that worked for me was to add the "saveToPhotoAlbum" parameter.
navigator.camera.getPicture(success, fail, {
quality: 80,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.CAMERA,
saveToPhotoAlbum: true
});
the following code for upload image
<a id="addImage" href="javascript:;">Add Image</a>
Javascript:
$().ready(function () {
var counter = 0;
$(function () {
var btnUpload = $('#addImage');
new AjaxUpload(btnUpload, {
action: 'saveupload.aspx',
name: 'uploadimage',
dataType: 'json',
onSubmit: function (file, ext) {
$("#loading").show();
},
onComplete: function (file, response) {
alert(response);
var uploadedfile = "UserData/" + file;
$("#uploadImageWrapper").append("
<div class='imageContainer offset' id='current" + counter + "'>
<img height='65px' width='65px' src='" + uploadedfile + "' alt='" + uploadedfile + "'/></div>");
$('#current' + counter).fadeIn('slow', function () {
$("#loading").hide();
$("#message").show();
$("#message").html("Added successfully!");
$("#message").fadeOut(3000);
counter++;
});
}
});
});
});
Server code: (saveupload.aspx.cs)
protected void Page_Load(object sender, EventArgs e)
{
HttpFileCollection uploadedFiles = Request.Files;
int i = 0;
string width = "0";
string height = "0";
if (uploadedFiles.Count > 0)
{
while (!(i == uploadedFiles.Count))
{
HttpPostedFile userPostedFile = uploadedFiles[i];
if (userPostedFile.ContentLength > 0)
{
string filename = userPostedFile.FileName.Substring(userPostedFile.FileName.LastIndexOf("\\") + 1);
userPostedFile.SaveAs(Path.Combine(Server.MapPath("UserData"), filename));
Bitmap img = new Bitmap(Path.Combine(Server.MapPath("UserData"), filename));
width = img.Width.ToString();
height = img.Height.ToString();
}
i += 1;
}
}
//I would like to return Uploaded image Height and Width
Response.Write(#"{Width:" + width + ", Height:" + height + "}");
}
and the return JsonResult is i have display in Alert message.
Problem:
I am not able to get response.Width and response.Height.
first of all I would suggest to clean the HTML of your saveupload.aspx. You do not need it and it pollutes your response.
You just need:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="saveupload.aspx.cs" Inherits="WebApplication1.saveupload" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Another thing; when you get the response back in your script you can use parseJSON, like this:
var obj = jQuery.parseJSON(response);
now you should be able to access Width and Height:
obj.Width
Last thing. Valums' Ajax Uploader has been replaced by the author with a new component.
You can find it here
It's very much similar but he's still updating this project so you might consider to switch.
UPDATE:
Another thing I would suggest is to use the jSon serializer (System.Web.Script.Serialization) to serialize the stream you want to return:
var jSon = new JavaScriptSerializer();
var OutPut = jSon.Serialize(myClass);
Response.Write(OutPut);