C# 如果浏览器关闭/上载被取消,如何停止文件传输
我正在用MVC3中的HTML5异步上传一个文件。如果我有一个大文件,比如1GB大小,并且在50%的上传完成后我取消上传或关闭浏览器,它仍然会在目标文件夹中保存一个500MB的文件 如何在控制器内部和客户端处理此问题 以下是我的控制器操作:C# 如果浏览器关闭/上载被取消,如何停止文件传输,c#,javascript,asp.net-mvc-3,html,file-upload,C#,Javascript,Asp.net Mvc 3,Html,File Upload,我正在用MVC3中的HTML5异步上传一个文件。如果我有一个大文件,比如1GB大小,并且在50%的上传完成后我取消上传或关闭浏览器,它仍然会在目标文件夹中保存一个500MB的文件 如何在控制器内部和客户端处理此问题 以下是我的控制器操作: [HttpPost] public ActionResult Upload(object fileToUpload1) { var fileName = Request.Headers["X-File-Name"]; var fileSize
[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);
首先,这不是应该使用任何客户端脚本来解决的问题,因为我不相信您在浏览器关闭时能够发出新的请求,而且当连接因网络问题而中断时,它肯定不会工作 所以我做了一些挖掘,但在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开发服务器和google chrome使用客户端代码进行测试
编辑:刚刚注意到Chuck Savage在之前的评论中发布了这一原则,所以向他推荐:)关注请求是忘记响应的原因,而响应可以判断客户端是否仍然连接(Response.IsClientConnected)。
通过简单地检查是否有需要阅读的内容,您可以忽略客户端可能存在的长(多长?)网络延迟的情况。
使用Chunk和Lukas方法,合并Response.IsClientConnected属性和您选择的线程睡眠,以防没有要读取的内容,但客户端仍处于连接状态。这样,如果需要,您可以提前退出读取循环,而无需从客户端用户生成WTF。您是否可以将文件大小与保存的大小进行比较,然后如果不是完整大小,则删除/不保存它?您是否可以告诉服务器[控制器]在接下来的事件中,另一个请求出现问题并删除任何具有特定名称/大小的文件?1.车身卸载2。中止/取消3。失败/错误。您可以在发出警报消息之后/之前执行此操作。请查看。请检查我的评论,如果可能的话,让我知道你的想法。