关于断点续传

28 天前
 humbass

最近一个项目要用到大文件的断点续传,多大文件呢,大的包可能会有 20G ,目前的做法是

前端取到文件后,按 2m 一个片段进行分片,然后逐个上传 后端收到完整的文件后放在一个隐藏的目录内,等最后的文件传完之后,逐一合并,并移动到指定的文件夹

实现是实现了,最大的问题不是上传,而是合并以及转移文件相当消耗时间

有没有更高级的做法呢?

4652 次点击
所在节点    Node.js
53 条回复
expy
27 天前
预分配一个完整文件,用分块序号和分块大小计算要写入的偏移量,前端上传前先查询,后端返回未上传的分块序号。
listen2wind
27 天前
@humbass #3 minio 是可以的,我们使用过,部署在内网的。
jorneyr
27 天前
4G 左右的文件计算 MD 需要 13+S ,这个耗时前后端都不可避免,需要验证文件的完整性是有必要的。

至于后端小文件合并成大文件,可以使用一个线程合并,也可以使用多个线程分部分合并,然后继续往上合并。
后端也可以使用文件内存映射直接写入文件中对应的 fragment ,不把收到的部分写入小文件。

具体要分析是哪个部分慢,例如是计算 MD5 32 慢,看看是否改成 MD5 16 也能够满足需求。
lerry
27 天前
有轮子就直接用。
minio 是 golang 实现的,很容易部署,我是用的 docker ,直接下载一个单文件应该也可以。
TOUJOURSER
27 天前
正好前段时间遇到类似的需求,我们采用的是 tus + minio
shenyansycn
27 天前
放硬盘里,人肉过去传输,最快。
unknown404
27 天前
请使用支持 S3 的相关存储(公有云对象存储或者私有云 minio),建议 op 好好重读下 http 的 RFC ,https://datatracker.ietf.org/doc/html/rfc7233#section-4.2 有标准的协议不用,你去造轮子
Rorysky
27 天前
@MoHen9 你说的是多线程下载,和断点续传有什么关系?
MoYi123
27 天前
@unknown404 这是下载, 不是上传.
xingjue
27 天前
minio
v2tudnew
27 天前
去看看 BT 软件是如何实现就完事了,只是把一对多改成一对一。
unknown404
27 天前
@MoYi123 原理一样的
duglik
27 天前
heiya
27 天前
我的做法是:
1.前端做好分片,为每一个分片生成序号,统计分片的个数。将这些数据传给后端,后端把这些数据记录下来,为这个文件生成一个全局 id ,返回给前端。
2.前端每次上传分片会连带文件 id+分片 id 一起传过来。分片文件会被上传到一个临时目录。每上传完成一个分片,后端会记录下来分片 id (分片序号)。如果是并发上传的话,要注意已上传分片 id 集合会有线程安全问题,不然会出现某个分片已上传但没记录的问题。
3.后端返回已上传分片集合。同时会有一个异步线程判断该文件 id 下的分片是否全都上传完毕。如果全都上传完成,调用文件系统 SDK 的合并文件方法(我用的是 minio ),合并完成之后,删除临时文件目录的分片。
4.与此同时,前端全部分片上传完成之后,循环调用获取文件合并状态接口。
完成~
klo424
27 天前
@humbass #15
1. 前端生成一个文件 id ,连带文件 size 、offset 和二进制数据传给后端。
2. 后端生成一个 size 大小的空文件,根据 id 找到文件,再根据 offset 去寻找位置写入二进制数据。
3. 后端写完数据返回成功,前端 offset 更新继续传下一个二进制数据给后端,以此循环。
4. 如果断了,下次打开页面时,从后端获取到未完成的文件 id ,再执行 1-3 过程。
cstj0505
27 天前
其实分片这东西完全是浏览器限制,不用 js,用个流式写入大文件直接边读边写
yaodong0126
27 天前
好家伙,你们但凡看过断点续传的原理,就说不出什么转移合并的话
trzzzz
27 天前
@heiya 透传 minio 的 uploadId 给前端,前端每次上传分片就带上 uploadId 和 partNumber 。服务器收到一片也不用写本地,直接透传到 minio ,我习惯这样。
但这样在弱网环境下会有问题,简单说个 流的 retry 需要自己写,这个是最麻烦的。如果是弱网还是建议先写 tmp 再异步上传
trzzzz
27 天前
@cstj0505 弱网环境或并发大场景下,流 reset 不好搞(最终还是需要缓存上传的数据)
ZZ74
27 天前
@klo424
复议 这才是断点续传的最初或者真实的做法。
OP 可以用这种方式避免重新组合文件。java 这边对应的 radomaccessfile....
另外为啥要组合?如果服务器不需要读取处理啥的,只是提供存储,直接存分片,下载的时候由前端拼也可以。
我不懂前端,你这 20G 的文件 前端下载时是否合并的了得打个问号

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1067088

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX