如何使用MVC 4上传大文件?

我有它的工作..但我注意到,一旦我上传的文件变得更大(约4000K)控制器将不会被称为..

所以我在chunking中join了哪个修正了这个问题..但是现在当我打开文件时它充满了垃圾字符…

那么用plupload / MVC 4上传大文件的正确方法是什么?

这是我目前的代码

$(document).ready(function () { var uploader = new plupload.Uploader({ runtimes: 'html5', browse_button: 'pickfiles', container: 'container', // max_file_size: '20000mb', url: '@Url.Action("Upload", "Home")', chunk_size: '4mb', //filters: [ // { title: "Excel files", extensions: "xls,xlsx" }, // { title: "Text files", extensions: "txt" } //], multiple_queues: true, multipart: true, multipart_params: { taskId: '' } }); 

和控制器

  [HttpPost] public ActionResult Upload(int? chunk, string name, string taskId) { string filePath = ""; var fileUpload = Request.Files[0]; var uploadPath = Server.MapPath("~/App_Data/Uploads"); chunk = chunk ?? 0; string uploadedFilePath = Path.Combine(uploadPath, name); var fileName = Path.GetFileName(uploadedFilePath); try { using (var fs = new FileStream(filePath, chunk == 0 ? FileMode.Create : FileMode.Append)) { var buffer = new byte[fileUpload.InputStream.Length]; fileUpload.InputStream.Read(buffer, 0, buffer.Length); fs.Write(buffer, 0, buffer.Length); } //Log to DB for future processing InstanceExpert.AddProcessStart(filePath, Int32.Parse(taskId)); } 

在web.config你需要这些(2GB左右):

 <system.web> <compilation debug="true" targetFramework="4.5" /> <httpRuntime targetFramework="4.5" maxRequestLength="2147483647" executionTimeout="1600" requestLengthDiskThreshold="2147483647" /> <security> <requestFiltering> <requestLimits maxAllowedContentLength="2147483647" /> </requestFiltering> </security> ... </system.web> 

当前版本

根据我写这个答案时使用的版本IIS 8.0的详细错误描述,您需要validationApplicationHost.config或Web中的configuration/ system.webServer / security / requestFiltering / requestLimits @ maxAllowedContentLength设置.config文件。 这意味着你需要包括:

 <requestLimits maxAllowedContentLength="20971520000"></requestLimits> 

内部configuration/ system.webServer / security / requestFiltering标签树。 以防万一你不能想象它到底在哪里,完整的代码块如下所示:

 <configuration> <system.webServer> <security> <requestFiltering> <requestLimits maxAllowedContentLength="20971520000"></requestLimits> </requestFiltering> </security> </system.webServer> </configuration> 

Visual Studio 2010 / .Net Framework 4和之前

使用VS2008 / 10和/或.Net Framework 3.5 / 4创build的遗留Web应用程序也可能仍然通过configuration/ system.web / httpRuntime @maxRequestLength查找此configuration,但正如链接页面所certificate的那样,不再可用,尽pipe不适用于此场景的HttpRuntime类自从.Net Framework 1.1以来仍然存在。 如果是这种情况,你需要包括:

 <httpRuntime maxRequestLength="20971520000" /> 

内部configuration/ system.web / httpRuntime标记树。 再一次,如果你不能理解它被插入的位置,完整的代码块如下所示:

 <configuration> <system.web> <httpRuntime maxRequestLength="20971520000" /> </system.web> </configuration> 

文件大小数字只是一个任意数字(20,000 MB – 而不是20 GB,而不是21,474,836,480)作为演示显示。 除非你为一个需要上传大文件的严密安全组织编写网站,否则你不应该让这么大的文件大小上传到你的networking服务器。

我遇到了这个问题,并在这里find了基于Jonathan代码的解决scheme。 他的代码有一些问题,但这是我的解决scheme。 如果你想上传一个大的文件,比如1Gbyte的文件,你必须通过几个请求来查找文件并发送(一个请求会超时)。 首先如前所述设置客户端和服务器端的最大限制。

 <system.webServer> <security> <requestFiltering> <requestLimits maxAllowedContentLength="2147483647" /> </requestFiltering> </security> <system.webServer> 

 <system.web> <httpRuntime targetFramework="4.5" maxRequestLength="2147483647" /> </system.web> 

然后块文件,并发送每个查克,等待响应,并发送下一个块。 这里是JavaScript和控制器代码。

  <div id="VideoDiv"> <label>Filename:</label> <input type="file" id="fileInput" /><br/><br/> <input type="button" id="btnUpload" value="Upload a presentation"/><br/><br/> <div id="progressbar_container" style="width: 100%; height: 30px; position: relative; background-color: grey; display: none"> <div id="progressbar" style="width: 0%; height: 100%; position: absolute; background-color: green"></div> <span id="progressbar_label" style="position: absolute; left: 35%; top: 20%">Uploading...</span> </div> </div> 

Javascript代码来查找,调用控制器和更新进度条:

  var progressBarStart = function() { $("#progressbar_container").show(); } var progressBarUpdate = function (percentage) { $('#progressbar_label').html(percentage + "%"); $("#progressbar").width(percentage + "%"); } var progressBarComplete = function() { $("#progressbar_container").fadeOut(500); } var file; $('#fileInput').change(function(e) { file = e.target.files[0]; }); var uploadCompleted = function() { var formData = new FormData(); formData.append('fileName', file.name); formData.append('completed', true); var xhr2 = new XMLHttpRequest(); xhr2.onload = function() { progressBarUpdate(100); progressBarComplete(); } xhr2.open("POST", "/Upload/UploadComplete?fileName=" + file.name + "&complete=" + 1, true); xhr2.send(formData); } var multiUpload = function(count, counter, blob, completed, start, end, bytesPerChunk) { counter = counter + 1; if (counter <= count) { var chunk = blob.slice(start, end); var xhr = new XMLHttpRequest(); xhr.onload = function() { start = end; end = start + bytesPerChunk; if (count == counter) { uploadCompleted(); } else { var percentage = (counter / count) * 100; progressBarUpdate(percentage); multiUpload(count, counter, blob, completed, start, end, bytesPerChunk); } } xhr.open("POST", "/Upload/MultiUpload?id=" + counter.toString() + "&fileName=" + file.name, true); xhr.send(chunk); } } $("#VideoDiv").on("click", "#btnUpload", function() { var blob = file; var bytesPerChunk = 3757000; var size = blob.size; var start = 0; var end = bytesPerChunk; var completed = 0; var count = size % bytesPerChunk == 0 ? size / bytesPerChunk : Math.floor(size / bytesPerChunk) + 1; var counter = 0; progressBarStart(); multiUpload(count, counter, blob, completed, start, end, bytesPerChunk); }); 

这里是上传控制器存储(“App_Data / Videos / Temp”),然后合并它们并存储在(“App_Data / Videos”)中:

 public class UploadController : Controller { private string videoAddress = "~/App_Data/Videos"; [HttpPost] public string MultiUpload(string id, string fileName) { var chunkNumber = id; var chunks = Request.InputStream; string path = Server.MapPath(videoAddress+"/Temp"); string newpath = Path.Combine(path, fileName+chunkNumber); using (FileStream fs = System.IO.File.Create(newpath)) { byte[] bytes = new byte[3757000]; int bytesRead; while ((bytesRead=Request.InputStream.Read(bytes,0,bytes.Length))>0) { fs.Write(bytes,0,bytesRead); } } return "done"; } [HttpPost] public string UploadComplete(string fileName, string complete) { string tempPath = Server.MapPath(videoAddress + "/Temp"); string videoPath = Server.MapPath(videoAddress); string newPath = Path.Combine(tempPath, fileName); if (complete=="1") { string[] filePaths = Directory.GetFiles(tempPath).Where(p=>p.Contains(fileName)).OrderBy(p => Int32.Parse(p.Replace(fileName, "$").Split('$')[1])).ToArray(); foreach (string filePath in filePaths) { MergeFiles(newPath, filePath); } } System.IO.File.Move(Path.Combine(tempPath, fileName),Path.Combine(videoPath,fileName)); return "success"; } private static void MergeFiles(string file1, string file2) { FileStream fs1 = null; FileStream fs2 = null; try { fs1 = System.IO.File.Open(file1, FileMode.Append); fs2 = System.IO.File.Open(file2, FileMode.Open); byte[] fs2Content = new byte[fs2.Length]; fs2.Read(fs2Content, 0, (int) fs2.Length); fs1.Write(fs2Content, 0, (int) fs2.Length); } catch (Exception ex) { Console.WriteLine(ex.Message + " : " + ex.StackTrace); } finally { if (fs1 != null) fs1.Close(); if (fs2 != null) fs2.Close(); System.IO.File.Delete(file2); } } } 

但是,如果两个用户同时上传同名的文件,会出现一些问题,您必须处理这个问题。 通过阅读responseText,你可以捕捉到一些错误和exception,并修剪它。