asp.net core分块上传文件示例
写完asp.net多文件上传后,感觉这种上传还是有很多缺陷,于是。。。(省略一万字,不废话)。这里我没用传统的asp.net,而选择了开源的asp.netcore,原因很简单,.netcore是.net新的开始,更是.net和.net开发者的未来,希望.net发展越来越好(大家的工资越来越高(●ˇ∀ˇ●))。
1.前端的实现:
1).html:
<html> <head> <metaname="viewport"content="width=device-width"/> <title>Index</title> <linkhref="/lib/bootstrap/dist/css/bootstrap.css"rel="externalnofollow"rel="stylesheet"/> <scriptsrc="/lib/jquery/dist/jquery.js"></script> <scriptsrc="/lib/bootstrap/dist/js/bootstrap.js"></script> <scriptsrc="/js/UploadJs.js"></script> </head> <body> <divclass="row"style="margin-top:20%"> <divclass="col-lg-4"></div> <divclass="col-lg-4"> <inputtype="text"value="请选择文件"size="20"name="upfile"id="upfile"style="border:1pxdotted#ccc"> <inputtype="button"value="浏览"onclick="path.click()"style="border:1pxsolid#ccc;background:#fff"> <inputtype="file"id="path"style="display:none"multiple="multiple"onchange="upfile.value=this.value"> <br/> <spanid="output">0%</span> <buttontype="button"id="file"onclick="UploadStart()"style="border:1pxsolid#ccc;background:#fff">开始上传</button> </div> <divclass="col-lg-4"></div> </div> </body> </html>
2).javascript:
varUploadPath=""; //开始上传 functionUploadStart(){ varfile=$("#path")[0].files[0]; AjaxFile(file,0); } functionAjaxFile(file,i){ varname=file.name,//文件名 size=file.size,//总大小shardSize=2*1024*1024, shardSize=2*1024*1024,//以2MB为一个分片 shardCount=Math.ceil(size/shardSize);//总片数 if(i>=shardCount){ return; } //计算每一片的起始与结束位置 varstart=i*shardSize, end=Math.min(size,start+shardSize); //构造一个表单,FormData是HTML5新增的 varform=newFormData(); 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++; varnum=Math.ceil(i*100/shardCount); $("#output").text(num+'%'); AjaxFile(file,i); if(result.mergeOk){ varfilepath=$("#path"); filepath.after(filepath.clone().val("")); filepath.remove();//清空inputfile $('#upfile').val('请选择文件'); alert("success!!!"); } } } }); }
这里的主要思路是利用html5Fileapi的slice方法把文件分块,然后new一个FormData()对象用于储存文件数据,之后就是递归调用AjaxFile方法直至上传完毕。
2.后台C#:
usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Threading.Tasks; usingMicrosoft.AspNetCore.Mvc; usingSystem.IO; //FormoreinformationonenablingMVCforemptyprojects,visithttp://go.microsoft.com/fwlink/?LinkID=397860 namespaceDotNet.Upload.Controllers { publicclassUploadController:Controller { //GET:/<controller>/ publicIActionResultIndex() { returnView(); } [HttpPost] publicasyncTask<ActionResult>UploadFile() { vardata=Request.Form.Files["data"]; stringlastModified=Request.Form["lastModified"].ToString(); vartotal=Request.Form["total"]; varfileName=Request.Form["fileName"]; varindex=Request.Form["index"]; stringtemporary=Path.Combine(@"E:\浏览器",lastModified);//临时保存分块的目录 try { if(!Directory.Exists(temporary)) Directory.CreateDirectory(temporary); stringfilePath=Path.Combine(temporary,index.ToString()); if(!Convert.IsDBNull(data)) { awaitTask.Run(()=>{ FileStreamfs=newFileStream(filePath,FileMode.Create); data.CopyTo(fs); }); } boolmergeOk=false; if(total==index) { mergeOk=awaitFileMerge(lastModified,fileName); } Dictionary<string,object>result=newDictionary<string,object>(); result.Add("number",index); result.Add("mergeOk",mergeOk); returnJson(result); } catch(Exceptionex) { Directory.Delete(temporary);//删除文件夹 throwex; } } publicasyncTask<bool>FileMerge(stringlastModified,stringfileName) { boolok=false; try { vartemporary=Path.Combine(@"E:\浏览器",lastModified);//临时文件夹 fileName=Request.Form["fileName"];//文件名 stringfileExt=Path.GetExtension(fileName);//获取文件后缀 varfiles=Directory.GetFiles(temporary);//获得下面的所有文件 varfinalPath=Path.Combine(@"E:\浏览器",DateTime.Now.ToString("yyMMddHHmmss")+fileExt);//最终的文件名(demo中保存的是它上传时候的文件名,实际操作肯定不能这样) varfs=newFileStream(finalPath,FileMode.Create); foreach(varpartinfiles.OrderBy(x=>x.Length).ThenBy(x=>x))//排一下序,保证从0-NWrite { varbytes=System.IO.File.ReadAllBytes(part); awaitfs.WriteAsync(bytes,0,bytes.Length); bytes=null; System.IO.File.Delete(part);//删除分块 } fs.Close(); Directory.Delete(temporary);//删除文件夹 ok=true; } catch(Exceptionex) { throwex; } returnok; } } }
这里的思路就是先保存每一个分块的文件到一个临时文件夹,最后再通过FileStream合并这些临时文件(合并时必需要按顺序)。后台的方法都进行了异步化(asyncawait真的非常好用),虽然不知道对效率有没有提升,但是就是觉得这样很酷。
源码下载:DotNet_jb51.rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。