您如何确保网页等待上传完成?

时间:2012-07-02 15:26:28

标签: c# asp.net-mvc asp.net-mvc-2

我有以下代码用于将大文件(~6MB)上传到ASP .NET MVC2应用程序。文件上传后,可能需要5分钟才能从控制器返回响应。

在此期间,IE9没有显示处理尚未完成的任何迹象,即用户可以选择其他文件并重新发布。

如何通知用户操作未完成,并在旧文件处理完成之前禁用提交按钮?

<% using (Html.BeginForm("InvoiceImport", "Grid", 
               FormMethod.Post, new { enctype = "multipart/form-data" }))
{%>
<input name="uploadFile" type="file" />
<input type="submit" name='invoice' value='Read'/>
<%} %>

控制器:

[AcceptVerbs(HttpVerbs.Post)]
[Authorize]
ActionResult ImportFromFile(HttpPostedFileBase uploadFile)
{
    Server.ScriptTimeout = 30 * 60;
    var res = ImportFromFile(uploadFile.InputStream); // takes lot of time
    TempData["Message"] = uploadFile.FileName + " Readed records " + res;
    return RedirectToAction("Complete");
}

更新

我认为最重要的问题是防止重复提交。 我尝试使用下面的代码来防止重复提交,但由于未知原因,Session [“Upload”]为空 如果第二次按下提交按钮。 如何防止重复提交?

View added

 <% if (TempData["Message"]!=null) { %>
   setTimeout( function() {
     showMessage ( '<%= TempData["Message"] as string %>');
    }, 300 );
    <% } %>


Controller

ActionResult ImportFromFile(HttpPostedFileBase uploadFile)
    {

        if (Session["Upload"] != null)
        {
            // todo: why this point is never reached ?
            TempData["Message"] = Session["Upload"] + " Please wait file is being processed";
            return View();
        }

        Session.Add("Upload", uploadFile.FileName);
        Server.ScriptTimeout = 30 * 60;
        ImportFromFile(uploadFile.InputStream);
        TempData["Message"] = uploadFile.FileName + " completed";
        Session.Remove("Upload");
        return RedirectToAction("Complete");
    }

4 个答案:

答案 0 :(得分:1)

使用asyncronus呼叫时,向用户显示呼叫正在进行中。查看this博文,了解长轮询,这样您就可以在流程结束时进行回复。

  1. 向用户显示他们已提交表单并禁用提交按钮。
  2. 进行Ajax调用以实际拨打电话并进行上传。
  3. 完成后告知用户作业已完成。
  4. 如果您担心他们会刷新页面并因此能够再次提交,您需要在后端跟踪他们的提交状态。某种锁定,以便您知道用户有正在运行的上传,并且他们无法再次上传。

答案 1 :(得分:1)

解决您问题的最简单方法是使用javascript禁用按钮和字段。你在我们的页面中有像jQuery这样的javascript库吗?

$('form').submit(function(){
   $(this).find('input').prop('disabled', true)
});

类似于jQuery的东西。如果您有多个表单,则可能需要向表单添加一个id以仅定位此表单。

更新:

由于重新提交的问题没有死的简单解决方案:

避免F5问题。确保在POST后重定向。你做了哪些,但我想如果需要很长时间,他们可能同时按F5。

我头脑中的一些解决方案可以解决这个问题。

  • (如果您使用的是SQL)生成一个guid,它放在表单页面的隐藏字段中。使其成为数据库中的唯一列,并将其与其余信息一起插入。如果他们尝试重新提交SQL将通过抛出您可以处理的异常来保护您。

  • 上述技术有其他选择。也许你将这些guid存储在一个单独的表中并检查它,或者可能是XML或缓存或其他什么。

  • 当您提交表单时,使用javascript添加时间戳。您在服务器上执行的第一件事是确保您在单击按钮后的x秒内。

  • 提交时(第一次提交后),您可以使用javascript添加警告。

    window.onbeforeunload = function(){return'已经保存了!请按否'; };

这最后一个解决方案并不安全,但很容易添加。

答案 2 :(得分:0)

您应该考虑使用Asyncronus控制器。

这样它将在一个单独的线程中运行上传,页面将不再锁定。

查看以下链接:

Using an Asychronous Controller

答案 3 :(得分:0)

考虑使用一些 ajaxified 上传解决方案,您可以向用户展示流程的进度,直到完成为止。

This SO回答提供了使用Valums ajax上传的详细示例。个人Darin喜欢这个解决方案。所以它应该是一个好的。