核心:
- 分段接收,分段解析,分段写文件
问题
-
Q:不同用户上传同一文件:
- A: 通过token加文件md5码解决,并且后期如果发现为同一文件甚至不需要上传,直接服务器cp一份
-
Q:同一个用户刷新上传(重复上传)
- A:通过会话id (processId: 通过token+md5 生成,防止上传重复上传同一文件,碎片共享同一个processId) & 碎片状态化: 杜绝重复上传碎片,同时实现断点续传
- Q: 为什么要token+md5
- A: 可以防止如下
- md5作用:防止A用户重复上传同一文件"
- 防止A用户重复上传同一文件"
- 防止A用户重复上传同一文件"
- token:防止A用户上传的碎片 跑到B碎片上 (既A,B上传类似碎片或者同一视频)
- A: 可以防止如下
- Q: 碎片有哪些状态:
- A: 传输失败 | 正在传输(因为是分段解析,所以会有中间状态) | 传输成功
- Q: 碎片共享同一个processId会出现数据冗余吗:
- A: 不会,processId并非uuid,只要是同一个文件以及同一个用户,必然相同
- Q: 为什么要token+md5
- Q: processId谁颁发:
- A: 前端颁发 | 后端颁发 ,延伸问题请看
进度条查询部分
- A: 前端颁发 | 后端颁发 ,延伸问题请看
- A:通过会话id (processId: 通过token+md5 生成,防止上传重复上传同一文件,碎片共享同一个processId) & 碎片状态化: 杜绝重复上传碎片,同时实现断点续传
-
Q: 进度条如何查询:
- Q: 碎片进度查询:
- A: 碎片有index(chunk)块的概念,缓存中存放了该碎片的总的容量,以及已经缓存的容量
- Q: 需要携带的参数:
- A: 文件的md5(
非碎片的md5,在本处无碎片md5的概念) & 碎片的chunk (代表第几块)- 切片还是需要携带MD5,并且是自身的md5,因为 processId和chunk 并不能代表这个chunk,md5可以
- Q: 如果 会话id是由服务器颁发 何时发起轮询请求:
- A: 完美的方式是当服务端收到请求之后通过webSocket通知前端
你收到本次会话的id了,发起轮询吧
若不采用websocket,则只能前端携带uuid给后端后,后端存储k-v(key为uuid,value为会话id),前端通过uuid轮询服务器获取会话id ,所以 会话id还不如前端颁发
- A: 完美的方式是当服务端收到请求之后通过webSocket通知前端
- A: 文件的md5(
- Q: 需要携带的参数:
- A: 碎片有index(chunk)块的概念,缓存中存放了该碎片的总的容量,以及已经缓存的容量
- Q: 文件进度查询:
- A: 已上传的部分累加 / 总数
- Q: 碎片进度如何更新: 通过BufferedInputStream 分段读取每次请求的数据,之后更新到缓存中 (既 分段解析)
- Q: 碎片进度查询:
-
Q: 何时合并文件,既何时结束
- A: 前端发起通知,后端开始合并碎片
- Q: 能否后端主动发起合并: 本项目中自己自动合并
- A: 可以,但是必须额外传递一个 总碎片数参数
- 单文件形式: ,后端判断是否是最后一块
- 多文件形式: 额外定义一个原子变量(可以优化到redis中)做累加,达到数目开启合并 ,但是必须要确保数据读取正确,不能有bab的问题,redis可以实现
- A: 可以,但是必须额外传递一个 总碎片数参数
- Q: 能否后端主动发起合并: 本项目中自己自动合并
- Q: 如何合并,全部读取再加载到内存中?
WIP
A: Java 暂时通过FileChannel实现
- A: 前端发起通知,后端开始合并碎片
-
Q: 如何断点续传:
- A: 服务端存储切片的唯一信息,写入的时候判断是否存在即可
-
Q: 如何分段写入到文件:
- 通过randAccessFile
-
Q: 在上传途中,服务器宕机怎么办,确切点说既缓存碎片状态的服务器挂了,数据清空了(保存在内存中)
- A: 既: 如果MD5等信息是存储在内存中,而磁盘碎片是存在的
- 要么是传输中途断了,既失败了同时缓存也丢了-> 删除|清空
- 要么是传输成功了,但是缓存丢了-> 依旧删除
- 所以,缓存丢了就删除
- A: 既: 如果MD5等信息是存储在内存中,而磁盘碎片是存在的
-
Q: 当合并的时候,合并失败:
对象:
上传对象
- chunk: 代表碎片下标
Talk is cheap , I am coding
- DEMO
- 更改文件名即可,支持进度展示,不需要sql,nosql