话前

一开始在做文件上传的时候,没考虑过文件上传失败的问题,因为上传的多数都是几十兆几百兆的文件。但是也有会上传比较大的文件,此时传统的上传直接没了反应,也不知道上传了多少就很头疼。后来网上搜索的关于大文件上传的思路,网上的思路还是蛮多的,都挺成熟的,然后就想把大文件分片下载这个技术引到项目中。最后也是成功引入分片上传和断点续传,还有大文件分片下载。本篇就来聊一聊大文件分片上传。

一、为什么要使用分片上传

要用分片上传,首先要知道为什么要使用分片上传,或者说那些场景下要使用分片上传。

1.文件过大:一个文件过大,几个G或者几十G的大文件就非常适合分片上传

2.网络不稳定:网络时好时坏或者比较慢的情况

3.断点续传:传了一部分后暂停想继续传的时候,分片上传也是个不错的选择(断点续传需要考虑其他因素,这里不做具体详情的讲说)

二、分片上传原理

了解了为什么要使用分片上传后,就要引入分片上传了。

分片上传的大致流程:前端对文件进行切片,然后分片发送到服务端。服务端接收到分片文件后保存相应的文件,并对每片做好排序(我是采用文件名前序号的方式),最后合并文件,这是总体流程。具体的流程如下:

1.客户端对将要上传的文件定义唯一标识,并对文件进行分片(每10兆为一片)

2.客户端调用服务端接口,进行上传文件片(客户端每次都要携带文件唯一标识,客户端可以每五个一组进行并行上传)

3.服务端用文件唯一标识建临时文件夹(用来存储文件片,最后方便在这个文件下删除文件片)

4.客户端每次上传完后根据服务端返回的结果判断该组的文件片是否都上传从成功,若有没成功的文件片,可以单独对该文件片进行重新上传

5.服务端根据上传文件夹中文件片的总和跟客户端分片的总和是否相等判断文件片是否都上传完成

6.分片文件上传完成后,服务端合并文件片,并删除临时文件夹中分片文件

三、具体的流程图

四、程序

分片上传要是做好,里面细节还是很多的,我是基于c#实现的。

/// <summary>
/// 文件上传返回结果的模型
/// </summary>
public class FileUploadModel
{ /// <summary>/// 当前片上传的状态,true表示当前片上传成功/// </summary>public bool IndexState { get; set; }/// <summary>/// 所有片是否上传完,true表示都已上上传完/// </summary>public bool TotalState { get; set; }/// <summary>/// 最后服务端文件存放的位置/// </summary>public string FilePath { get; set; }/// <summary>/// 提示信息/// </summary>public string Message { get; set; }
}/// <summary>
/// 上传文件
/// </summary>
/// <param name="folderId">文件唯一ID</param>
/// <param name="fileName">文件名</param>
/// <param name="total">总片数</param>
/// <param name="index">当前片数索引</param>
/// <returns></returns>
[DisableRequestSizeLimit]
[HttpPost]
public ActionResult<string> UploadBigFile([FromForm] string folderId, [FromForm] string fileName, [FromForm] int total, [FromForm] int index)
{var filePath = Path.Combine(dirPath, folderId);if (System.IO.Directory.Exists(filePath))System.IO.Directory.CreateDirectory(filePath);//filePath=Path.Combine(filePath, fileName);var resultModel=new FileUploadModel();filePath = Path.Combine(dirPath, index + "_" + fileName);//1.判断当前片是否存在,存在的话,可以直接跳过继续上传,有点断点续传那么点意思if (System.IO.File.Exists(filePath)){resultModel = new FileUploadModel { IndexState = true, TotalState = true, Message="当前片已经存在,继续上传" };return JsonHelper.SerializeObjectToUpper(new ResultModel(true, resultModel));}var data = Request.Form.Files;if (!DataFileBlockExist(filePath)){using (var fileStream = new FileStream(filePath, FileMode.Create)){foreach (var file in data){file.CopyTo(fileStream); //保存文件}}}//2.判断是不是已经上传完if (System.IO.File.Exists(filePath) && !DataTransComplete(dirPath, "_" + fileName, total)){resultModel = new FileUploadModel {  IndexState = true, TotalState = false };return JsonHelper.SerializeObjectToUpper(new ResultModel(true, resultModel));}//3.合并判断,//如果已经是最后一个分片,组合//当然你也可以用其它方法比如接收每个分片时直接写到最终文件的相应位置上,//但要控制好并发防止文件锁冲突if (DataTransComplete(dirPath, "_" + fileName, total)){var filepath = Path.Combine(dirPath, fileName);try{//4.独占方式进行文件写入!防止在合并文件的过程中又发生文件合并操作     using (FileStream fs = new FileStream(filepath, FileMode.Create, FileAccess.Write, FileShare.None)){for (int i = 1; i <= total; ++i){string part = Path.Combine(dirPath, i + "_" + fileName);var bytes = System.IO.File.ReadAllBytes(part);fs.Write(bytes, 0, bytes.Length);bytes = null;//5.删除对应的分片System.IO.File.Delete(part);}var fileid = Guid.NewGuid();var extName = fs.Name.GetExtensioName();//var fileName = Path.GetFileName(filepath);fs.Close();//6.上传完成;var resultPath = Path.Combine(webAttPath, folderId,fileName);resultModel = new FileUploadModel { IndexState = true, TotalState = false ,FilePath= resultPath };return JsonHelper.SerializeObjectToUpper(new ResultModel(true, resultModel));}}catch (Exception ex){NLoggerHelper.Logger.Error(ex.Message);resultModel = new FileUploadModel { IndexState = false, TotalState = false,Message=ex.Message };return JsonHelper.SerializeObjectToUpper(new ResultModel(false, resultModel));}}resultModel = new FileUploadModel { IndexState = false, TotalState = false };return JsonHelper.SerializeObjectToUpper(new ResultModel(false, resultModel));
}/// <summary>
/// 当前索引的文件块 是否存在;
/// </summary>
/// <param name="path">文件存储位置</param>
/// <param name="name">文件名</param>
/// <param name="index">块索引</param>
/// <returns></returns>
private bool DataBlockExist(string path, string name, int index)
{string file = Path.Combine(path, index + "_" + name);if (System.IO.File.Exists(file))return true;elsereturn false;}/// <summary>
/// 当前索引的文件块 是否存在;
/// </summary>
/// <param name="filePath">文件路径</param>
/// <returns></returns>
private bool DataFileBlockExist(string filePath)
{if (System.IO.File.Exists(filePath))return true;elsereturn false;}

大文件分片上传、断点续传相关推荐

  1. minio实现大文件分片上传+断点续传+预览

    minio实现大文件分片上传+断点续传+预览 只提供后端java代码 思路: 前端分片 校验文件md5是否已经存在 --不存在创建临时桶存分片 校验分块是否已经上传 分块上传 合并分块 校验合成后md ...

  2. vue实现大文件分片上传断点续传并展示上传进度条

    最近有一个上传视频到服务器的功能,然后发现视频太大了,比如1个G的视频文件基本都是上传失败的,我之前都是上传阿里云的,所以面对大文件上传服务器就做了分片上传和断点续传. 首先解释什么是分片上传:比如一 ...

  3. 大文件分片上传,断点续传,秒传 实现

    前段时间做视频上传业务,通过网页上传视频到服务器. 视频大小 小则几十M,大则 1G+,以一般的HTTP请求发送数据的方式的话,会遇到的问题:1,文件过大,超出服务端的请求大小限制:2,请求时间过长, ...

  4. 大文件分片上传前端框架_无插件实现大文件分片上传,断点续传

    文件上传.gif 1. 简介: 本篇文章基于实际项目的开发,将介绍项目中关于大文件分片上传.文件验证.断点续传.手动重试上传等需求的使用场景及实现: 2. 项目需求 在一个音视频的添加中,既要有音视频 ...

  5. 无插件实现大文件分片上传,断点续传

    代码地址如下: http://www.demodashi.com/demo/11888.html 1. 简介: 本篇文章基于实际项目的开发,将介绍项目中关于大文件分片上传.文件验证.断点续传.手动重试 ...

  6. 使用webuploader组件实现大文件分片上传,断点续传

    无组件断点续传.gif 1. 组件简介 webuploader:是一个以HTML5为主, Flash为辅的文件上传组件,采用大文件分片/并发上传的方式,极大地提高了文件上传的效率,同时兼容多种浏览器版 ...

  7. 大文件分片上传前端框架_基于Node.js的大文件分片上传

    基于Node.js的大文件分片上传 我们在做文件上传的时候,如果文件过大,可能会导致请求超时的情况.所以,在遇到需要对大文件进行上传的时候,就需要对文件进行分片上传的操作.同时如果文件过大,在网络不佳 ...

  8. iOS 利用AFNetworking实现大文件分片上传

    概述 一说到文件上传,想必大家都并不陌生,更何况是利用AFNetworking(PS:后期统称AF)来做,那更是小菜一碟.比如开发中常见的场景:头像上传,九宫格图片上传...等等,这些场景无一不使用到 ...

  9. React大文件分片上传方案

    最近做了大文件(文件夹)分片上传的需求,记录一下. 原理: 前端进行大文件分片上传的方案几乎都是利用Blob.prototype.slice方法对文件进行分片,用数组将每一个分片存起来,最后将分片发给 ...

最新文章

  1. 有关sql server 2000的数据类型
  2. php中的魔术函数以及魔术常量
  3. 【OpenCV3】cv::divide()使用详解
  4. BIRT:基于 Eclipse 的报表
  5. jQuery 库 - 特性
  6. SAP CRM product category search - hidden search attribute
  7. JsonRequestBehavior.AllowGet 方便浏览器调试
  8. 只工作不玩耍_不玩耍:独立游戏开发商的经验教训
  9. linux同步多台机器的时间
  10. 使用 session_destroy() 销毁session文件时 报 Trying to destroy uninitialized session 错误解决办法
  11. 总结js中数据类型的bool值及其比较
  12. java overload
  13. Java刷题细节知识点汇总——partThree
  14. HTTP Live Streaming直播(iOS直播)技术分析与实现
  15. ccf二十四点Java_CCF--二十四点 - osc_kel5e0sw的个人空间 - OSCHINA - 中文开源技术交流社区...
  16. python flask教程
  17. 网站不让复制文字??教你破解复制+白嫖下载百度等各种文档
  18. linux配置Jexus发布asp.net网站
  19. “十四五”地表水水质国控断面坐标位置数据(共3613个点位,含断面名称、所在流域、所在水体、水体类型、经度、纬度、断面属性、所在省份、所在地市)
  20. 象棋python代码_象的解释|象的意思|汉典“象”字的基本解释

热门文章

  1. attribute属性
  2. esxi license过期_Vcenter 和ESXi License过期解决办法
  3. vue中进入页面,自动触发一次点击事件
  4. 通用电力线载波(UPLC)行业调研报告 - 市场现状分析与发展前景预测
  5. 生物质发电项目动态,最新生物质发电项目汇总
  6. 正确认识区块链与元宇宙的关系
  7. CSS Tutorial for Beginners
  8. Unity2D入门1 简单角色移动与动画 基础
  9. 关于 tomcat9 下载后启动不了的问题
  10. linux查看cpupower模式,Linux - cpupower调整CPU主频