[toc]html
上一篇net core WebApi——文件分片上传与跨域请求处理介绍完文件的上传操做,原本是打算紧接着写文件下载,中间让形形色色的事给耽误的,今天仍是抽个空整理完文件这块儿,而后就能够鼓捣别的东西了。前端
这里咱们仍然使用基础工程,须要下载的朋友请移步net core Webapi 总目录,代码都是与博客的进度基本同步的。 上传的时候咱们介绍过度片的思路,而下载也同样,只是客户端与服务端角色转换下就行了。 后端linux
前端后端
文件下载相对于上传来讲稍微简洁点儿,若是不考虑服务器压力也能够一个a标签解决下载问题,分片的意义就在于每次与服务端的交互减小流量,有些时候咱们推荐拿空间换时间,但对于大流量来讲仍是慢慢来比较好,单次访问量若是大再加上多并发怕是服务器会受不了,因此有了一片片分步来循环访问这个方法。api
也是直接来看代码吧,咱们在FileController建立几个接口方法RequestDownloadFile,FileDownload。跨域
/// <summary> /// 请求下载文件 /// </summary> /// <param name="fileInfo">文件参数信息[name]</param> /// <returns></returns> [HttpPost, Route("RequestDownload")] public MessageEntity RequestDownloadFile([FromBody]Dictionary<string, object> fileInfo) { } /// <summary> /// 分段下载文件 /// </summary> /// <param name="fileInfo">请求参数信息[index,name]</param> /// <returns></returns> [HttpPost, Route("Download")] public async Task<IActionResult> FileDownload([FromBody]Dictionary<string, object> fileInfo) { }
RequestDownloadFile服务器
这里说明下,与服务端的操做都要尽量多的确认身份信息(固然后续会有说这块儿),文件的相关操做也同样须要而且还要严格点儿,我这里就是为了作示例演示因此只传文件信息便可。并发
public MessageEntity RequestDownloadFile([FromBody]Dictionary<string, object> fileInfo) { MessageEntity message = new MessageEntity(); string fileName = string.Empty; string fileExt = string.Empty; if (fileInfo.ContainsKey("name")) { fileName = fileInfo["name"].ToString(); } if (fileInfo.ContainsKey("ext")) { fileExt = fileInfo["ext"].ToString(); } if (string.IsNullOrEmpty(fileName)) { message.Code = -1; message.Msg = "文件名不能为空"; return message; } //获取对应目录下文件,若是有,获取文件开始准备分段下载 string filePath = $".{AprilConfig.FilePath}{DateTime.Now.ToString("yyyy-MM-dd")}/{fileName}"; filePath = $"{filePath}{fileExt}"; FileStream fs = null; try { if (!System.IO.File.Exists(filePath)) { //文件为空 message.Code = -1; message.Msg = "文件还没有处理完"; return message; } fs = new FileStream(filePath, FileMode.Open); if (fs.Length <= 0) { //文件为空 message.Code = -1; message.Msg = "文件还没有处理完"; return message; } int shardSize = 1 * 1024 * 1024;//一次1M RequestFileUploadEntity request = new RequestFileUploadEntity(); request.fileext = fileExt; request.size = fs.Length; request.count = (int)(fs.Length / shardSize); if ((fs.Length % shardSize) > 0) { request.count += 1; } request.filedata = GetCryptoString(fs); message.Data = request; } catch (Exception ex) { LogUtil.Debug($"读取文件信息失败:{filePath},错误信息:{ex.Message}"); } finally { if (fs != null) { fs.Close(); } } return message; }
FileDownloadapp
public async Task<IActionResult> FileDownload([FromBody]Dictionary<string, object> fileInfo) { //开始根据片断来下载 int index = 0; if (fileInfo.ContainsKey("index")) { int.TryParse(fileInfo["index"].ToString(), out index); } else { return Ok(new { code = -1, msg = "缺乏参数" }); } string fileName = string.Empty; string fileExt = string.Empty; if (fileInfo.ContainsKey("name")) { fileName = fileInfo["name"].ToString(); } if (fileInfo.ContainsKey("ext")) { fileExt = fileInfo["ext"].ToString(); } if (string.IsNullOrEmpty(fileName)) { return Ok(new { code = -1, msg = "文件名不能为空" }); } //获取对应目录下文件,若是有,获取文件开始准备分段下载 string filePath = $".{AprilConfig.FilePath}{DateTime.Now.ToString("yyyy-MM-dd")}/{fileName}"; filePath = $"{filePath}{fileExt}"; if (!System.IO.File.Exists(filePath)) { return Ok(new { code = -1, msg = "文件还没有处理" }); } using (var fs = new FileStream(filePath, FileMode.Open)) { if (fs.Length <= 0) { return Ok(new { code = -1, msg = "文件还没有处理" }); } int shardSize = 1 * 1024 * 1024;//一次1M int count = (int)(fs.Length / shardSize); if ((fs.Length % shardSize) > 0) { count += 1; } if (index > count - 1) { return Ok(new { code = -1, msg = "无效的下标" }); } fs.Seek(index * shardSize, SeekOrigin.Begin); if (index == count - 1) { //最后一片 = 总长 - (每次片断大小 * 已下载片断个数) shardSize = (int)(fs.Length - (shardSize * index)); } byte[] datas = new byte[shardSize]; await fs.ReadAsync(datas, 0, datas.Length); //fs.Close(); return File(datas, "application/x-gzip"); } }
看过上传的朋友都清楚上传是三步,请求上传=>开始上传=>合并,而下载只须要两步,由于合并与否其实不那么重要了,反正文件流都给客户端了,那边本身判断须要从新下载仍是下载部分片断都是他们本身的事了(服务端只管卖,东西有问题本身解决,多理想的状态)。async
搞完以后从新生成,运行以后咱们来测试下效果,测试以前不要忘了接口白名单(作过登陆相关的验证操做的忽略这点)。
这里提示error是由于解析错误,实际请求下载测试是正常的,若是有异常问题能够与我联系。
文件相关的上传下载以及常规信息的操做能够告一段落,至于下一步鼓捣点儿啥也还没想好,原本还在看着linux相关的操做作发布部署的铺垫,看最近整体的进度吧,总之,学如逆水行舟,若是不想溺水,就握好你的浆(固然有些人不用浆那就算了,告辞)。