This question is not totally answered, please fell free to contribute !
I'm trying to display a simple progress bar
while a large form is submitted.
The form contains a dozen of fields, plus some file upload fields, where the user can select a picture. Then, when he clicks on a Create
button, the form with data and pictures are submitted and the entity is created in DB. (only one click to submit the form AND the pictures).
Everything works fine, but I'd like to display a progress bar during the submit process.
I have found a lot of tutorials explaining how to display a progress bar, but I don't find anyone explaining how to display a progress bar indicating the percentage of work accomplished by a method, ie, I'd like to see 10%, 25%, etc… during the submit process.
So, basically, this is what I've done : (this is an ASP.NET MVC3 project)
@model MyModel
@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "target-form", enctype = "multipart/form-data" }))
{
//some Html.TextBoxFor() and other @Html.DropDownListFor
@Html.TextBoxFor(m => m.File, new { type = "file"})
<input type="submit" value="Create" class="submitButton" />
<div id="progressBar"></div>
}
And a basic controller
[HttpPost]
public ActionResult Create(MyModel model)
{
if (ModelState.IsValid)
{
DALLayer dal = new DALLayer()
dal.AddEntity(model);
return RedirectToAction("Index", "Home");
}
return null;
}
Is it possible to transform my last <div>
in a progressBar
displaying the state of upload progress ?
Here are my requirements :
- No plugin (this is a personnal project, I want to understand how to do this by myself).
- Cross compatible, IE8+ (if possible)
- jQuery ok, but no Flash.
Thank you very much !
UPDATE 1
Here is a JSFIDDLE, where I'm trying to adapt this link but without success… If you think you can help, you're welcome !
UPDATE 2
Ok, I used acarlon's answer to submit my form with XMLHttpRequest
and the datas are correcty posted to the controller. However, the ProgressBar still doesn't appear !
I just replace the data passed to the controller by :
formData = new FormData(document.getElementById("target-form") );
xhr.open("POST", "@Url.Action("MyMethod", "MyController")", true );
and try some different headers, like :
xhr.setRequestHeader("X-File-Name", $('#Files_0__File')[0].files[0].name);
xhr.setRequestHeader("X-File-Size", $('#Files_0__File')[0].files[0].size);
xhr.setRequestHeader("X-File-Type", $('#Files_0__File')[0].files[0].type);
//Also tried with "Content-Length" but it doesn't care about it.
(It was hardcoded here to be sure it has good values. I'll do it in a loop when I'll be more at ease with it.)
And when I submit my form, the XMLHttpRequest
send has these fields :
readyState: 4
status: 0 <= should be 200, right ?
And in the error handler
, I have these values :
loaded: 0
total: 883526
type: "error"
So the data are submitted to my controller, but I'm unable to display this damned progressbar…
Best Answer
You can use
XMLHttpRequest
to receive updates when uploading files. There are also various jquery-type wrappers to achieve the same. I will describe a solution usingXMLHttpRequest
. First intercept the form submit.Then create XHR request:
Then register to be notified about progress events:
Open XHR passing in any arguments (
id
is shown as an example)Then in the controller:
You will receive the updates in the update handler.
Extension for long running server task
If there is some long running task on the server (such as writing the data to the database), then you need to chunk the operations (so that you can give updates on completion of each chunk) on the server and implement code to handle a long running service that you can query from javascript. See here. The basic idea is to start the task on the server side and periodically check the progress from Javascript. You may want to have two separate progress bars, one for uploading and one for the server side operation. This provides more information to the user - they will know that the file upload is complete and now some server-side operation is happening.