[MVC]多文件、超大文件上传
话不多说,上代码。
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script> <script> var page = { init: function () { $("#upload").click($.proxy(this.upload, this)); }, upload: function () { var shardSize = 2 * 1024 * 1024, //以2MB为一个分片 shardCount = 0, succeed = 0; for (var i = 0; i < $("#file")[0].files.length; i++) { shardCount += Math.ceil($("#file")[0].files[i].size / shardSize); //总片数 } for (var j = 0; j < $("#file")[0].files.length; j++) { var file = $("#file")[0].files[j], //文件对象 name = file.name, //文件名 size = file.size; //总大小 //var shardSize = 2 * 1024 * 1024, //以2MB为一个分片 // shardCount = Math.ceil(size / shardSize); //总片数 var Count = Math.ceil(file.size / shardSize); for (var i = 0; i < Count; ++i) { //计算每一片的起始与结束位置 var start = i * shardSize, end = Math.min(size, start + shardSize); //构造一个表单,FormData是HTML5新增的 var form = new FormData(); form.append("data", file.slice(start, end)); //slice方法用于切出文件的一部分 form.append("name", name); form.append("total", Count); //总片数 form.append("index", i + 1); //当前是第几片 $("#output").text(0 + " / " + shardCount); //Ajax提交 $.ajax({ url: "/UpDown_File/Upload", type: "POST", data: form, async: true, //异步 processData: false, //很重要,告诉jquery不要对form进行处理 contentType: false, //很重要,指定为false才能形成正确的Content-Type success: function (s) { //alert(s); if (s.Error == 1) { //alert("上传失败!"); } ++succeed; $("#output").text(succeed + " / " + shardCount); if (succeed == shardCount) { $("#output").text("完成"); } }, error: function (e) { //alert(e); if (e.Error == 1) { //alert("上传失败!"); } } }); } } } }; $(function () { page.init(); }); </script> </head> <body> <div> <input type="file" id="file" multiple="multiple" accept=".jpg,.png,.jpeg,.ai,.psd,.tif,.txt,.svg,.rar,.zip,.docx,.pptx,.xlsx" /> <button id="upload">上传</button> <span id="output" style="font-size: 12px">等待</span> </div> </body>
[HttpPost] public ActionResult Upload() { //从Request中取参数,注意上传的文件在Requst.Files中 string name = Request["name"]; int total = Convert.ToInt32(Request["total"]); int index = Convert.ToInt32(Request["index"]); var data = Request.Files["data"]; //保存一个分片到磁盘上 string dir = Server.MapPath("~/Upload"); string file = Path.Combine(dir, name + "_" + index); data.SaveAs(file); string[] files = Directory.GetFiles(dir, name + "*"); //如果已经是最后一个分片,组合 //当然你也可以用其它方法比如接收每个分片时直接写到最终文件的相应位置上,但要控制好并发防止文件锁冲突 if (files.Length == total) { file = Path.Combine(dir, name); var fs = new FileStream(file, FileMode.Create); for (int i = 1; i <= total; ++i) { string part = Path.Combine(dir, name + "_" + i); var bytes = System.IO.File.ReadAllBytes(part); fs.Write(bytes, 0, bytes.Length); bytes = null; System.IO.File.Delete(part); } fs.Close(); } //返回是否成功,此处做了简化处理 return Json(new { Error = 0 }); }