asp.net core分块上传文件示例
程序员文章站
2022-06-29 17:43:06
写完asp.net多文件上传后,感觉这种上传还是有很多缺陷,于是。。。(省略一万字,不废话)。这里我没用传统的asp.net,而选择了开源的asp.net core,原因很...
写完asp.net多文件上传后,感觉这种上传还是有很多缺陷,于是。。。(省略一万字,不废话)。这里我没用传统的asp.net,而选择了开源的asp.net core,原因很简单,.net core是.net新的开始,更是.net和.net开发者的未来,希望.net发展越来越好(大家的工资越来越高(●ˇ∀ˇ●))。
1.前端的实现:
1).html:
<html> <head> <meta name="viewport" content="width=device-width" /> <title>index</title> <link href="/lib/bootstrap/dist/css/bootstrap.css" rel="external nofollow" rel="stylesheet" /> <script src="/lib/jquery/dist/jquery.js"></script> <script src="/lib/bootstrap/dist/js/bootstrap.js"></script> <script src="/js/uploadjs.js"></script> </head> <body> <div class="row" style="margin-top:20%"> <div class="col-lg-4"></div> <div class="col-lg-4"> <input type="text" value="请选择文件" size="20" name="upfile" id="upfile" style="border:1px dotted #ccc"> <input type="button" value="浏览" onclick="path.click()" style="border:1px solid #ccc;background:#fff"> <input type="file" id="path" style="display:none" multiple="multiple" onchange="upfile.value=this.value"> <br /> <span id="output">0%</span> <button type="button" id="file" onclick="uploadstart()" style="border:1px solid #ccc;background:#fff">开始上传</button> </div> <div class="col-lg-4"></div> </div> </body> </html>
2).javascript:
var uploadpath = ""; //开始上传 function uploadstart() { var file = $("#path")[0].files[0]; ajaxfile(file, 0); } function ajaxfile(file, i) { var name = file.name, //文件名 size = file.size, //总大小shardsize = 2 * 1024 * 1024, shardsize = 2 * 1024 * 1024,//以2mb为一个分片 shardcount = math.ceil(size / shardsize); //总片数 if (i >= shardcount) { return; } //计算每一片的起始与结束位置 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("lastmodified", file.lastmodified); form.append("filename", name); form.append("total", shardcount); //总片数 form.append("index", i + 1); //当前是第几片 uploadpath = file.lastmodified //ajax提交文件 $.ajax({ url: "/upload/uploadfile", type: "post", data: form, async: true, //异步 processdata: false, //很重要,告诉jquery不要对form进行处理 contenttype: false, //很重要,指定为false才能形成正确的content-type success: function (result) { if (result != null) { i = result.number++; var num = math.ceil(i * 100 / shardcount); $("#output").text(num + '%'); ajaxfile(file, i); if (result.mergeok) { var filepath = $("#path"); filepath.after(filepath.clone().val("")); filepath.remove();//清空input file $('#upfile').val('请选择文件'); alert("success!!!"); } } } }); }
这里的主要思路是利用html5 file api的slice方法把文件分块,然后new一个formdata()对象用于储存文件数据,之后就是递归调用ajaxfile方法直至上传完毕。
2.后台c#:
using system; using system.collections.generic; using system.linq; using system.threading.tasks; using microsoft.aspnetcore.mvc; using system.io; // for more information on enabling mvc for empty projects, visit http://go.microsoft.com/fwlink/?linkid=397860 namespace dotnet.upload.controllers { public class uploadcontroller : controller { // get: /<controller>/ public iactionresult index() { return view(); } [httppost] public async task<actionresult> uploadfile() { var data = request.form.files["data"]; string lastmodified = request.form["lastmodified"].tostring(); var total = request.form["total"]; var filename = request.form["filename"]; var index = request.form["index"]; string temporary = path.combine(@"e:\浏览器", lastmodified);//临时保存分块的目录 try { if (!directory.exists(temporary)) directory.createdirectory(temporary); string filepath = path.combine(temporary, index.tostring()); if (!convert.isdbnull(data)) { await task.run(() => { filestream fs = new filestream(filepath, filemode.create); data.copyto(fs); }); } bool mergeok = false; if (total == index) { mergeok = await filemerge(lastmodified, filename); } dictionary<string, object> result = new dictionary<string, object>(); result.add("number", index); result.add("mergeok", mergeok); return json(result); } catch (exception ex) { directory.delete(temporary);//删除文件夹 throw ex; } } public async task<bool> filemerge(string lastmodified,string filename) { bool ok = false; try { var temporary = path.combine(@"e:\浏览器", lastmodified);//临时文件夹 filename = request.form["filename"];//文件名 string fileext = path.getextension(filename);//获取文件后缀 var files = directory.getfiles(temporary);//获得下面的所有文件 var finalpath = path.combine(@"e:\浏览器", datetime.now.tostring("yymmddhhmmss") + fileext);//最终的文件名(demo中保存的是它上传时候的文件名,实际操作肯定不能这样) var fs = new filestream(finalpath, filemode.create); foreach (var part in files.orderby(x => x.length).thenby(x => x))//排一下序,保证从0-n write { var bytes = system.io.file.readallbytes(part); await fs.writeasync(bytes, 0, bytes.length); bytes = null; system.io.file.delete(part);//删除分块 } fs.close(); directory.delete(temporary);//删除文件夹 ok = true; } catch (exception ex) { throw ex; } return ok; } } }
这里的思路就是先保存每一个分块的文件到一个临时文件夹,最后再通过filestream合并这些临时文件(合并时必需要按顺序)。后台的方法都进行了异步化(async await真的非常好用),虽然不知道对效率有没有提升,但是就是觉得这样很酷。
源码下载:dotnet_jb51.rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。