缓冲和流式传输是上传文件的两种常用方案,这里主要演示流式传输。
1.Net Core MVC Form提交方式: 前端页面 form表单提交:
1 <form id="uploadForm"> 2 图片上传: <input type="file" name="file" multiple value="选择" onchange="doUpload()" id="ajaxfile" /> 3 </form> 4 <script type="text/javascript"> 5 //图片上传 6 function doUpload() 7 { 8 var formData = new FormData($("#uploadForm")[0]); 9 $.ajax({10 url: ‘@Url.Action("FileSave", "FileUpload")‘,11 type: ‘POST‘,12 data: formData,13 async: false,14 cache: false,15 contentType: false,16 processData: false,17 success: function (returndata) {18 //成功后执行的方法19 },20 error: function (returndata) {21 //上传失败执行的方法22 }23 });24 }25 </script>
后端方法: 采用的流式处理,请求收到文件,然后应用直接处理或者保存。这种传输无法提高性能,但优点是可降低上传时对内存或磁盘空间的需求。 通过流(stream)把请求收到的文件拷贝到系统指定的文件中。
1 2 [HttpPost] 3 public async Task<IActionResult> FileSave() 4 { 5 //获取Form提交的文件 6 var files = Request.Form.Files; 7 long size = files.Sum(f => f.Length); 8 string webRootPath = _hostingEnvironment.WebRootPath; //物理路径 9 string contentRootPath = _hostingEnvironment.ContentRootPath;10 string showfilePath = "";11 foreach (var formFile in files)12 {13 if (formFile.Length > 0)14 {15 int count = formFile.FileName.Split(‘.‘).Length;16 string fileExt = formFile.FileName.Split(‘.‘)[count - 1]; //文件扩展名,不含“.”17 long fileSize = formFile.Length; //获得文件大小,以字节为单位18 string newFileName = System.Guid.NewGuid().ToString() + "." + fileExt; //随机生成新的文件名19 #region 文件夹不存在则创建20 var filePath = webRootPath + "/upload";21 if (!Directory.Exists(filePath))22 {23 Directory.CreateDirectory(filePath);24 }25 #endregion26 #region 文件不存在则新建27 filePath = webRootPath + "/upload/" + newFileName;28 showfilePath = "upload/" + newFileName;29 FileHelper.CreateFile(filePath);30 #endregion31 //把上传的图片复制到指定的文件中32 using (var stream = new FileStream(filePath, FileMode.Create))33 {34 await formFile.CopyToAsync(stream);35 }36 }37 }38 return Ok(new { count = files.Count, savepath = showfilePath });39 }
2.基于Base64的方式 前端用Vue提交,调用后端接口 vue提交用FormData方式,params方提交的参数会放到Url末尾,导致过长超出,这里用FormData的方式提交 提交时传递的参数要通过FormData对象来添加 Vue提交方法:
1 //上传图片 2 3 afterRead(file) { 4 // 此时可以自行将文件上传至服务器 5 let obj={}; 6 var imgurl=file.content 7 //需要将文件的地址 需要去掉base64头部标签 这里简单用replace替换 8 imgurl = imgurl.replace("data:image/jpeg;base64,", ""); 9 //获取图片的格式10 var Img=file.file.name.split(‘.‘)[1]11 12 //创建formdata对象 传递参数13 var formdata=new FormData();14 formdata.append("fileBase64",imgurl);//添加一条数据15 formdata.append("fileExt",Img);//添加一条数据16 17 //ajax调用接口,ajax的参数配置18 this.$ajax({19 method: ‘post‘,20 dataType:‘json‘,21 url: "http://*****/FileUpload/UploadBase64",22 contentType : false,// 告诉jQuery不要去设置Content-Type请求头23 processData: false,// 告诉jQuery不要去处理发送的数据,24 beforeSend : function(req) {25 req.setRequestHeader(‘Content-Type‘, ‘application/json‘); ///加这一行解决问题26 },27 data: formdata28 }).then(res=>{29 //图片上传成功后 执行的操作30 var msg=res.data.msg31 32 }).catch(error =>{33 console.log(error)34 })35 },
后端方法:原理和1基本相同
1 [HttpPost] 2 3 public string UploadBase64(string fileBase64,string fileExt) 4 { 5 TableData data = new TableData(); 6 byte[] bytes = ToBytes_FromBase64Str(fileBase64); 7 //var fileExtension = Path.GetExtension(fileName); 8 9 string webRootPath = _hostingEnvironment.WebRootPath;10 string newFileName = System.Guid.NewGuid().ToString() + "." + fileExt; //随机生成新的文件名11 12 var filePath = webRootPath + "/upload";13 var RetfilePath = "upload/" + newFileName;14 if (!Directory.Exists(filePath))15 {16 Directory.CreateDirectory(filePath);17 }18 filePath = webRootPath + "/upload/" + newFileName;19 try20 {21 data.code = 200;22 FileStream fs = new FileStream(filePath, FileMode.CreateNew);23 fs.Write(bytes, 0, bytes.Length);24 fs.Close();25 data.msg = RetfilePath;26 }27 catch (Exception ex)28 {29 data.code = 500;30 data.msg = "newFileName:"+ newFileName+"Error:"+ex.Message;31 }32 return JsonHelper.Instance.Serialize(data);33 }
附:FileHelper类 和TableData类
1 public static class FileHelper 2 { 3 4 /// <summary> 5 /// 拷贝文件 6 /// </summary> 7 /// <param name="orignFile">原始文件</param> 8 /// <param name="newFile">新文件路径</param> 9 public static void FileCoppy(string orignFile, string newFile)10 {11 if (string.IsNullOrEmpty(orignFile))12 {13 throw new ArgumentException(orignFile);14 }15 if (string.IsNullOrEmpty(newFile))16 {17 throw new ArgumentException(newFile);18 }19 System.IO.File.Copy(orignFile, newFile, true);20 }21 /// <summary>22 /// 删除文件23 /// </summary>24 /// <param name="path">路径</param>25 public static void FileDel(string path)26 {27 if (string.IsNullOrEmpty(path))28 {29 throw new ArgumentException(path);30 }31 System.IO.File.Delete(path);32 }33 /// <summary>34 /// 移动文件35 /// </summary>36 /// <param name="orignFile">原始路径</param>37 /// <param name="newFile">新路径</param>38 public static void FileMove(string orignFile, string newFile)39 {40 if (string.IsNullOrEmpty(orignFile))41 {42 throw new ArgumentException(orignFile);43 }44 if (string.IsNullOrEmpty(newFile))45 {46 throw new ArgumentException(newFile);47 }48 System.IO.File.Move(orignFile, newFile);49 }50 //创建路径51 public static void CreatePath(string FilePath)52 {53 if (!Directory.Exists(FilePath))54 {55 Directory.CreateDirectory(FilePath);56 }57 }58 //创建文件59 public static void CreateFile(string FilePath)60 {61 if (!File.Exists(FilePath))62 {63 FileStream fs = File.Create(FilePath);64 fs.Close();65 }66 }67 }
1 public class TableData 2 { 3 /// <summary> 4 /// 状态码 5 /// </summary> 6 public int code; 7 /// <summary> 8 /// 操作消息 9 /// </summary>10 public string msg;11 /// <summary>12 /// 总记录条数13 /// </summary>14 public int count;15 16 /// <summary>17 /// 数据内容18 /// </summary>19 public dynamic data;20 public TableData()21 {22 code = 200;23 msg = "加载成功";24 25 }26 }
演示效果如下: