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

4 回答 4

1

在使用异步调用时,向用户显示调用正在进行中。查看博客文章以了解长轮询,这将允许您进行在进程完成时返回的调用。

  1. 向用户显示他们已提交表单并禁用提交按钮。
  2. 进行 Ajax 调用以实际进行调用并进行上传。
  3. 当它完成时通知用户作业已经完成。

如果您担心他们会刷新页面并因此能够再次提交,您需要在后端跟踪他们的提交状态。某种锁定,因此您会知道用户正在运行上传,并且他们应该无法再次上传。

于 2012-07-02T15:46:24.777 回答
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 '已经保存!请按否'; };

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

于 2012-07-02T15:58:43.050 回答
0

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

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

查看以下链接:

使用异步控制器

于 2012-07-02T15:33:25.073 回答
0

考虑使用一些ajaxified上传解决方案,您可以在其中向用户显示过程的进度,直到完成。

这个SO 答案给出了使用Valums ajax 上传的详细示例。个人达林喜欢这个解决方案。所以应该是不错的。

于 2012-07-02T15:47:07.117 回答