Ajax load script for multiple files, jQuery ASP.NET MVC
I am working on loading script for ASP.NET MVC application. I have an implementation that works on a single file, but I would like to extend that to handle multiple uploads. Here's the original implementation:
Upload View (yes, I will be moving this jQuery code into its own file):
<script type="text/javascript">
var fieldCount = 0;
function addField() {
var name = 'file' + fieldCount;
var row = 'row' + fieldCount;
var str = '<p id="' + row + '"><label for="' + name + '">File to upload: <input type="file" name="' + name + '" id="' + name + '" />(100MB max size) <a onclick="removeRow(\'#' + row + '\'); return false;">[-]</a></label></p>';
fieldCount++;
$("#fields").append(str);
};
function removeRow(id) {
if ($("#fields").children().size() > 1) {
$(id).remove();
}
};
$(function() {
$("#ajaxUploadForm").ajaxForm({
iframe: true,
dataType: "json",
beforeSubmit: function() {
$("#resultBox").show();
$("#status").html('<h1><img src="/Content/busy.gif" /> Uploading file...</h1>');
},
success: function(result) {
$("#ajaxUploadForm").unblock();
$("#ajaxUploadForm").resetForm();
var tcolor;
var msg;
if (!result.message) {
tcolor = "red";
msg = result.error;
}
else {
tcolor = "green";
msg = result.message;
}
$("#resultBox").show();
$("#status").html('<span style="color:' + tcolor + ';">' + msg + '</span>').animate({ opacity: 1.0 }, 3000).fadeOut('slow', function() {
$("#resultBox").hide();
});
},
error: function(xhr, textStatus, errorThrown) {
$("#ajaxUploadForm").unblock();
$("#ajaxUploadForm").resetForm();
$("#resultBox").add("p").attr("id", "status").css("margin-top", "15px").css("padding", "20px");
$("#status").html('<span style="color:red;">Error uploading file</span>').animate({ opacity: 1.0 }, 3000).fadeOut('slow', function() {
$("#resultBox").hide();
});
}
});
});
</script>
<form id="ajaxUploadForm" action="<%= Url.Action("AjaxUpload", "Upload")%>" method="post" enctype="multipart/form-data">
<fieldset id="uploadFields">
<legend>Upload a file</legend>
<div id="fields"></div>
<input id="ajaxUploadButton" type="submit" value="Submit" />
</fieldset>
<a onclick="addField(); return false;" id="add">Add</a>
<div id="resultBox">
<p id="status" style="margin:10px;"></p>
</div>
</form>
Act:
public FileUploadJsonResult AjaxUpload(HttpPostedFileBase file)
{
Upload fileToUpload;
try
{
fileToUpload = new Upload
{
filename = file.FileName,
filesize = file.ContentLength,
date = DateTime.Now,
id = Guid.NewGuid()
};
var savedFileName = Server.MapPath(Path.Combine(@"~/uploads", Path.GetFileName(fileToUpload.filename)));
if (System.IO.File.Exists(savedFileName))
{
throw new Exception(string.Format("The file '{0}' already exists on the server.", file.FileName));
}
file.SaveAs(savedFileName);
}
catch (Exception ex)
{
return new FileUploadJsonResult { Data = new { error = string.Format("Upload failure: {0}", ex.Message), message = string.Empty } };
}
return new FileUploadJsonResult { Data = new { message = string.Format("{0} uploaded successfully. (id:{1})", Path.GetFileName(file.FileName), fileToUpload.id) } };
}
I used the concepts from this blog post to turn the whole thing upside down.
Now with my javascript for adding / removing fields, I slightly changed the result of the action:
public List<FileUploadJsonResult> AjaxUpload(HttpPostedFileBase fileBase)
{
var results = new List<FileUploadJsonResult>();
try
{
if (Request.Files.Count > 0)
{
Upload uploadFile;
for (var i = 0; i <= (Request.Files.Count - 1); i++)
{
HttpPostedFileBase file = Request.Files[i];
uploadFile = new Upload
{
filename = file.FileName,
filesize = file.ContentLength,
date = DateTime.Now,
id = Guid.NewGuid()
};
var savedFileName = Server.MapPath(Path.Combine(@"~/uploads", Path.GetFileName(uploadFile.filename)));
if (System.IO.File.Exists(savedFileName))
{
results.Add(new FileUploadJsonResult { Data = new { error = string.Format("Upload failure: {0}", string.Format("The file '{0}' already exists on the server.", file.FileName)), message = string.Empty } });
}
file.SaveAs(savedFileName);
results.Add(new FileUploadJsonResult { Data = new { message = string.Format("{0} uploaded successfully", file.FileName) } });
}
}
}
catch (Exception ex)
{
results.Add(new FileUploadJsonResult { Data = new { error = string.Format("Upload failure: {0}", ex.Message), message = string.Empty } });
}
return results;
}
I'm kind of stuck at this point. Loading works fine, but errors in javascript due to my returning a list and not a single item. My guess is that if I change this part of the code to iterate over the list of results, it can be done.
Another thing I would like to do is after each file has finished downloading to add the success text to the resultBox.
Any help would be appreciated! Thank!
source to share
Hiya, you have to return ActionResult here, you cannot return a list of them. Also, you are using the Request.Files collection, so you don't need to use the HttpPostedFileBase in your action.
something like this might help you
public FileUploadJsonResult AjaxUpload() {
try {
foreach (string name in Request.Files) {
var file = Request.Files[name];
if (!string.IsNullOrEmpty(file.FileName)) {
file.SaveAs( Server.MapPath(Path.Combine(@"~/uploads", Path.GetFileName(file.FileName)));
}
}
} catch (Exception ex) {
return new FileUploadJsonResult {
Data = new {
error = string.Format("Upload failure: {0}", ex.Message),
message = string.Empty
}
};
}
return new FileUploadJsonResult {
Data = new {
message = "file(s) uploaded successfully"
}
};
}
Also, you may need HttpModule to provide a progress bar , the example uses jQuery.form plugin and jquery ui progress bar
source to share