技术调研:云文件打包压缩下载至客户端,不在服务器落盘

2020-11-24 09:05:02 +08:00
 Visitor233

RT,现在文件都是放在阿里云 OSS 存储。客户多选文件下载,肯定是打包成一个压缩包的。我现在是将文件流 stream 放在 dic 字典里,然后运行 ICSharpCode.SharpZipLib 这个包里的 Zip.ZipOutputStream 方法进行后续处理,将生成的 byte 放在 response 的 body 里。前端再下载响应内容。

试了下,下载几张图片是正常的压缩包形式,解压正常。但下载内容包含一个 400 多 M 的视频时,服务就卡了 2 分钟,然后前端下了个空压缩包。

请大佬们指点下,老实说我感觉这方法不靠谱。

2338 次点击
所在节点    程序员
17 条回复
kingfalse
2020-11-24 09:06:44 +08:00
大文件不压缩呗?
xuanbg
2020-11-24 09:09:23 +08:00
落盘就是正常的文件下载,客户端可以断线续传,可以分段下载,可以……各种骚操作。不落盘你还能玩什么?多来几个大文件同时下载,别的不说,你服务器的内存就要爆掉了。
imdong
2020-11-24 09:10:39 +08:00
使用 JS 加载回来后在浏览器端进行打包处理?

但是我不知道 zip 之类的压缩是否需要等所有文件都加载完毕后才能生成压缩文件的头部。

如果有可以顺序加载的话,可以考虑客户端一边读取一边生成压缩包下载。
xuanbg
2020-11-24 09:14:17 +08:00
@imdong 没压缩完文件长度都不知道啊,怎么生成头部?
imdong
2020-11-24 09:16:51 +08:00
查了一下 zip 的包结构(不确定是否正确)

```
[local file header + file data + data descriptor]{1,n} + central directory + end of central directory record

[文件头+文件数据+数据描述符]{此处可重复 n 次}+核心目录+目录结束标识

当压缩包中有多个文件时,就会有多个[文件头+文件数据+数据描述符]
```

如果包结构是这样的话,应该是可以做到 边加载 边压缩 边输出下载。

应该叫 流压缩?那九成九是已经有现成的轮子可以用(除非无法实现)。

至于是在浏览器端处理还是在服务端处理,见仁见智吧。
Visitor233
2020-11-24 09:17:37 +08:00
@xuanbg 我也是这么觉得的,400M,我的小电脑就死了。
@kingfalse 现在不确定用户的文件大小,而且项目赶,求稳。
@imdong 涨知识了,之前在阿里文档中看到过一篇介绍边下载边解压的技术,可惜没提供代码
imdong
2020-11-24 09:18:28 +08:00
@xuanbg 如一楼所说,不压缩,只归档,我们应该是可以做到提前知道文件的一些已知信息如大小。
wanguorui123
2020-11-24 09:20:58 +08:00
HTTP 实时返回压缩流,不要打包再下载
Akkuman
2020-11-24 09:21:11 +08:00
可以实现,golang 中就有类似的,打包的输出流写入 resp writer,不断 flush
shuax
2020-11-24 09:21:19 +08:00
搞 tar 格式,别压缩
imdong
2020-11-24 09:27:17 +08:00
https://stuk.github.io/jszip/documentation/examples/downloader.html

看到这个 jszip 的库可以实现在客户端加载远程文件生成压缩文件输出到下载。

但是这个似乎需要等所有的文件都加载完毕后才能压缩并输出下载,大文件可能会造成浏览器崩溃?

应该有更佳实现,同步输出下载的,@Akkuman #9 证明这种方案是一定可行的。

至于如何实现,抛针引线,楼主自己努力找一下吧。
okaku
2020-11-24 09:37:10 +08:00
这些可以在前端解决。zip 本身支持无压缩只归档。
但是在前端无法实现从浏览器下载管理器中的断点续传。只能从 web 页面上断点续传。
前端实现在对一些手机浏览器的兼容上有差异。
Joyuce
2020-11-24 09:46:04 +08:00
服务器打包上传 oss,给客户端链接,带宽压力不就在 oss 了
Fred0410
2020-11-24 09:58:35 +08:00
teambition 的网盘用的就是这个放方法
wangritian
2020-11-24 10:15:08 +08:00
ecs 的流量很贵吧,给 oss 开 cdn,带宽峰值收费,下载 api 拆成 2 个,1 个接收文件列表、指定压缩包路径、异步打包、立即返回路径,此时界面可以显示“正在压缩...”,第 2 个循环访问 cdn 路径,直到成功下载或超时
wunonglin
2020-11-24 10:37:26 +08:00
oss 不是有打包的计算函数?直接用不就行了?
forcecharlie
2020-11-24 10:44:30 +08:00
@imdong HTTP chunk 编码可以满足
@xuanbg 如果使用 Golang 直接将 Zip 的输出流 io.Copy 到 http.ResponseWriter 内存消耗也比较低 实际上压缩都可以这么玩,就算是 tar.gz 也可以这样压缩解压输出到 HTTP 响应,并不需要占用很多的内存,但 CPU 反正不低,Git 代码托管平台存储库 archive 下载很多就是这个思路,当然其中涉及到缓存,即通过 io.MultiWriter 写入到磁盘和 Hash.

C# 的则需要自己封装一下。

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

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

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

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

© 2021 V2EX