javascript 显示一个显示表单提交进度的进度条
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21902385/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Displaying a progress bar showing the progress of a form submission
提问by AlexB
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 lotof 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)
我试图在progress bar
提交一个大表单时显示一个简单的。
该表单包含十几个字段,以及一些文件上传字段,用户可以在其中选择图片。然后,当他单击一个Create
按钮时,提交带有数据和图片的表单,并在 DB 中创建实体。(只需单击一次即可提交表格和图片)。
一切正常,但我想在提交过程中显示一个进度条。
我找到了很多解释如何显示进度条的教程,但我没有找到任何人解释如何显示进度条,指示方法完成的工作百分比,即,我希望看到 10%, 25% 等...在提交过程中。
所以,基本上,这就是我所做的:(这是一个 ASP.NET MVC3 项目)
@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 ?
是否可以将我的最后<div>
一个转换为progressBar
显示上传进度的状态?
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.
- 没有插件(这是一个个人项目,我想自己了解如何做到这一点)。
- 交叉兼容,IE8+(如果可能)
- jQuery 好的,但没有 Flash。
Thank you very much !
UPDATE 1Here is a JSFIDDLE, where I'm trying to adapt this linkbut without success... If you think you can help, you're welcome !
UPDATE 2Ok, I used acarlon's answerto 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 :
非常感谢你 !
更新 1这是一个JSFIDDLE,我正在尝试调整此链接但没有成功...如果您认为可以提供帮助,欢迎您!
更新 2好的,我使用acarlon 的回答来提交我的表单,XMLHttpRequest
并且数据已正确发布到控制器。但是,ProgressBar 仍然没有出现!
我只是将传递给控制器的数据替换为:
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 :
当我提交表单时,XMLHttpRequest
发送有以下字段:
readyState: 4
status: 0 <= should be 200, right ?
readyState: 4
status: 0 <= 应该是 200,对吧?
And in the error handler
, I have these values :
而在error handler
,我有这些价值观:
loaded: 0
total: 883526
type: "error"
加载:0
总计:883526
类型:“错误”
So the data are submitted to my controller, but I'm unable to display this damned progressbar...
所以数据被提交给我的控制器,但我无法显示这个该死的进度条......
回答by acarlon
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 using XMLHttpRequest
.
First intercept the form submit.
您可以XMLHttpRequest
在上传文件时使用接收更新。还有各种 jquery 类型的包装器来实现相同的目的。我将使用XMLHttpRequest
. 首先拦截表单提交。
$("#target-form").submit(function () {
Then create XHR request:
然后创建 XHR 请求:
xhr = new XMLHttpRequest();
Then register to be notified about progress events:
然后注册以接收有关进度事件的通知:
xhr.upload.addEventListener( "progress", function ( evt )
{
if( evt.lengthComputable )
{
var progressPercent = ( evt.loaded / evt.total ) * 100;
showProgress( value );//your function.
}
}, false );
//Some other events you will probably want to subscribe to
xhr.addEventListener( "load", function ()
{
fileUploadComplete( this.responseText );
}, false );
xhr.addEventListener( "error", function ( first, second, third )
{
fileUploadComplete( "Error: Image format not supported." );
}, false );
xhr.addEventListener( "abort", function ()
{
fileUploadComplete( "Error: Upload was cancelled. Please try again." );
}, false );
Open XHR passing in any arguments (id
is shown as an example)
打开 XHR 传入任何参数(id
作为示例显示)
xhr.open( "post", '@Html.Raw( @Url.Action( "UploadImage", new { someId = id } ) )', true );
// Set appropriate headers
xhr.setRequestHeader( "Content-Type", "multipart/form-data" );
xhr.setRequestHeader( "X-File-Name", name );
// Send the file
xhr.send( file );
Then in the controller:
然后在控制器中:
public ActionResult UploadImage( int someId, HttpPostedFileBase userFile )
{
...
}
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.
如果服务器上有一些长时间运行的任务(例如将数据写入数据库),那么您需要在服务器上对操作进行分块(以便您可以在每个块完成时提供更新)并实现代码来处理您可以从 javascript 查询的长期运行服务。见这里。基本思想是在服务器端启动任务,并定期从 Javascript 中检查进度。您可能需要两个单独的进度条,一个用于上传,另一个用于服务器端操作。这为用户提供了更多信息——他们将知道文件上传已完成,现在正在发生一些服务器端操作。
回答by MarzSocks
Add an ajax timer control which checks progress with the server and set time interval (say every 2 seconds).
添加一个 ajax 计时器控件,用于检查服务器的进度并设置时间间隔(例如每 2 秒)。
Execute your server task on a new thread. This will cause your post back to return immediately whilst executing your long task in the background. Start the ajax timer.
在新线程上执行服务器任务。这将导致您的帖子在后台执行您的长期任务时立即返回。启动 ajax 计时器。
As the long task works let it update a session variable which contains the % work done.
随着长任务的工作,让它更新一个包含完成工作百分比的会话变量。
When the timer postbacks to the sever, fetch the % work done from the session variable.
当计时器回发到服务器时,从会话变量中获取完成的工作百分比。
You can design a progress bar by having an inner div and an outer div. Set the width of the inner div to the % work done: $('#progressBarWorkDone').css('width', WorkDone + '%');
您可以通过具有内部 div 和外部 div 来设计进度条。将内部 div 的宽度设置为 % work done: $('#progressBarWorkDone').css('width', WorkDone + '%');
<div id="progressBar" style="width:400px;">
<div id="progressBarWorkDone" style="width:0px;height:10px;background-color:red;"><div/>
<div/>
Note, if you don't know how to use the timer control, you can also execute AJAX calls from javascript using setInterval(function(){ AJAX CALLBACK GOES HERE },1000);
请注意,如果您不知道如何使用计时器控件,您也可以使用 setInterval(function(){ AJAX CALLBACK GOES HERE },1000); 从 javascript 执行 AJAX 调用。
However having said all that it way simpler to just put an animated gif inside your progress bar div. Hide the div, and then show the div when the submit button is clicked.
然而,说了这么多,把一个动画 gif 放在你的进度条 div 中会更简单。隐藏 div,然后在单击提交按钮时显示 div。
<input type="submit" onclick="$('#progressBar').show();" value="Create" class="submitButton" />
<div id="progressBar" style="display:none;"><img src="myProgressBar.gif" /></div>