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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。