2011-12-06 57 views
4

我上传文件与HTML5在MVC3异步。如果我有一个大文件,比如1GB大小,并且在上传完成50%后,我取消上传或关闭浏览器,它仍然会在目标文件夹中保存一个500MB的文件。如何停止文件传输,如果浏览器关闭/上传取消

如何在控制器和客户端处理这个问题?

这里是我的控制器操作:

[HttpPost] 
public ActionResult Upload(object fileToUpload1) 
{ 
    var fileName = Request.Headers["X-File-Name"]; 
    var fileSize = Request.Headers["X-File-Size"]; 
    var fileType = Request.Headers["X-File-Type"]; 

    Request.SaveAs("D:\\uploadimage\\" + fileName, false); 

    if (fileToUpload1 == null) 
    { 
     return Json(true, JsonRequestBehavior.AllowGet); 
    } 
    else { return Json(false, JsonRequestBehavior.AllowGet); } 

    // return Json(false, JsonRequestBehavior.AllowGet); 
} 

这里是JavaScript:

// Uploading - for Firefox, Google Chrome and Safari 
xhr = new XMLHttpRequest(); 

// Update progress bar 
xhr.upload.addEventListener("progress", uploadProgress, false); 

function uploadProgress(evt) { 
    if (evt.lengthComputable) { 
     var percentComplete = Math.round(evt.loaded * 100/evt.total);  

     //assign value to prgress bar Div 
     var progressBar = document.getElementById("progressBar"); 

     progressBar.max = evt.total; 
     progressBar.value = evt.loaded; 
    } 
} 

// File load event 
xhr.upload.addEventListener("load", loadSuccess, false); 

function loadSuccess(evt) { 
    $(fileParentDivobj).find(".ImgDiv").find("span").html("uploaded"); 
    addfile(fileParentDivobj); 
} 

//handling error 
xhr.addEventListener("error", uploadFailed, false); 
xhr.addEventListener("abort", uploadCanceled, false); 

function uploadFailed(evt) { 
    alert("There was an error attempting to upload the file."); 
} 

function uploadCanceled(evt) { 
    alert("The upload has been canceled by the user or the browser dropped the connection."); 
} 

xhr.open("POST", "@Url.Action("Upload","Home")", true); 

// Set appropriate headers 
xhr.setRequestHeader("Cache-Control", "no-cache"); 
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); 
xhr.setRequestHeader("Content-Type", "multipart/form-data"); 
xhr.setRequestHeader("X-File-Name", file.fileName); 
xhr.setRequestHeader("X-File-Size", file.fileSize); 
xhr.setRequestHeader("X-File-Type", file.type); 
xhr.setRequestHeader("X-File", file); 

// Send the file (doh) 
xhr.send(file); 
+3

难道你不能比较文件大小与你保存的大小,然后如果它不是全尺寸,删除/不保存它? –

+0

难道你不能告诉服务器[控制器]以下事件与另一个请求,有些事情出错了,并删除任何具有特定名称/大小的文件? 1.身体卸载2.中止/取消3.失败/错误。您可以在警报消息之后/之前执行此操作。 – codeSetter

回答

4

首先,这是不是应该使用任何客户端脚本,我不加以解决相信当浏览器关闭时您将能够提出新的请求,并且当连接因网络问题而中断时肯定无法工作。

所以我做了一些挖掘,我还没有发现什么在asp.net会告诉我,请求连接被中断。但是,我们可以检查我们收到的数据量以及我们应该收到的数据量!

public ActionResult Upload() 
{ 
    // I like to keep all application data in App_Data, feel free to change this 
    var dir = Server.MapPath("~/App_Data"); 
    if (!Directory.Exists(dir)) 
     Directory.CreateDirectory(dir); 

    // extract file name from request and make sure it doesn't contain anything harmful 
    var name = Path.GetFileName(Request.Headers["X-File-Name"]); 
    foreach (var c in Path.GetInvalidFileNameChars()) 
     name.Replace(c, '-'); 

    // construct file path 
    var path = Path.Combine(dir, name); 

    // this variable will hold how much data we have received 
    var written = 0; 
    try 
    { 
     using (var output = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) 
     { 
      var buffer = new byte[0x1000]; 
      var read = 0; 

      // while there is something to read, write it to output and increase counter 
      while ((read = Request.InputStream.Read(buffer, 0, buffer.Length)) > 0) 
      { 
       output.Write(buffer, 0, read); 
       output.Flush(); 

       written += read; 
      } 
     } 
    } 
    finally 
    { 
     // once finished (or when exception was thrown) check whether we have all data from the request 
     // and if not - delete the file 
     if (Request.ContentLength != written) 
      System.IO.File.Delete(path); 
    } 

    return Json(new { success = true }); 
} 

测试使用asp.net开发服务器和谷歌Chrome使用您的客户端代码。

编辑:刚刚发现野人查克已经张贴在早些时候的评论这一原则,所以道具给他:)

+0

请看看http://stackoverflow.com/questions/41572040/cancel-file-upload-on-server-when-cancelled-from-client/41576645#41576645。 请检查我的意见,如果可能的话,让我知道你的想法。 –

0

关注请求是用来遗忘的时间响应的原因,可以说,如果客户端仍连接或没有( Response.IsClientConnected)。
通过简单的检查是否有东西可以读取,您忽略了客户端可能的长时间(多长时间?)网络延迟的情况。
使用Chunk和Lukas方法并合并Response.IsClientConnected属性和线程的睡眠状态以防万一没有任何可读取但客户端仍处于连接状态。通过这种方式,如果需要的话,您可以先退出读取循环,而不会从客户端用户生成WTF。

相关问题