Go+Vue.js 如何较好的实现 Web 下载大文件?

2022-12-30 10:13:50 +08:00
 Frankcox
最近在尝试实现一个功能,从 k8s Container 中导出文件下载。目前已经能够获取到文件流,但是在返回给前端时出现了问题,我尝试直接使用 io.Copy 将文件流 Copy 到 response 的 responseWriter 中,前端使用 fetch 请求下载。但是该模式会有一个问题,就是触发下载请求后,浏览器会一直等待后端返回数据,在文件流加载好之后直接提示下载完成。而不像平常下载那样有下载进度条。这种情况我推测是 response 是完全加载好文件数据流后再一次返回,使用 wireshark 抓包时可能因为一次数据量过大( 500 多 MB )直接卡死。
不怎么懂前端,我想知道有没有较好的方式能将文件流直接返回给前端实现下载,使用 ws 下载也行。
3247 次点击
所在节点    Go 编程语言
32 条回复
Frankcox
2022-12-30 11:07:35 +08:00
@rekulas
@okakuyang
@AlphaTr
感谢,请问有这块的相关文档文章吗,我去看看
timnottom
2022-12-30 11:10:22 +08:00
Frankcox
2022-12-30 11:11:24 +08:00
@timnottom 谢谢
rekulas
2022-12-30 11:39:52 +08:00
https://blogs.360.net/post/%E7%94%A8-filesystem-api-%E5%AE%9E%E7%8E%B0%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BD%BD%E5%99%A8.html
如果非要用 js 下载可以通过 filesystem 的方式,现在有不少新生服务都喜欢这个模式,优点是比较灵活
Frankcox
2022-12-30 11:49:54 +08:00
@rekulas 感谢,我之前用 js 发请求主要是为了 header 添加信息处理鉴权,用 a.href 直接下载的话虽然解决了下载的问题,但会有权限的问题,我再看看这块。
gogogo2000
2022-12-30 13:39:19 +08:00
@Frankcox 添加鉴权的话你需要用 worker 方式拦截浏览器的下载请求,然后在 worker 中把 header 加上去
weiwoxinyou
2022-12-30 14:30:55 +08:00
有鉴权需求可以试试成熟的 axios 请求库
darknoll
2022-12-30 15:10:31 +08:00
@Frankcox 你可以把 token 直接放到 URL 的查询参数里面啊
hellojukay
2022-12-30 18:23:36 +08:00
别处理下载流量过程,把下载交给浏览器来干,模拟一个 a 标签点击事件。
webcape233
2023-02-12 00:14:07 +08:00
@Frankcox 你好,我最近也遇到类似问题,似乎通过 xhr 模式(例如用 axios 或 fetach ),无论怎么写,总是要等待 response 获取完毕才能继续处理,如果使用 blob 模式,大文件就会有很大问题,res 过程中刷新页面就中断了,浏览器自身下载管理也无法接管下载,等 blob 构建完成实际上再弹出的浏览器下载框就快完成下载动作了。 现在策略是 acios 去请求下载的临时地址,这样后台能鉴权,后台认可后返回下载地址和地址和一个专用的下载 key ,key 存 cookie 中,再构造一个 a 标签(加上 download 属性),href 写为临时地址( rudownload/hdjkkdnf )然后点击 a 标签,这样后台监听 download 这个路由,就能取到临时地址和 cookie ,cokkie 用来鉴定权限,临时地址对应下载的资源(怎么对应的方法很多,例如临时地址和对应资源地址存到数据库), 后端返回文件即可。 不知道还有啥方法不,我能找到由浏览器来接管下载的方法就是这样了。
webcape233
2023-02-12 00:19:03 +08:00
当然,其实也可以省掉前面一步,直接用 a 标签来下载,带上 cookie 进行认证
Frankcox
2023-02-12 16:45:03 +08:00
@webcape233 我用的也是类似这个模式,用户发送请求后,后端不执行下载而是根据信息返回一个临时 token ,前端获取到 token 再进行实际下载请求,我同时将这个实际下载请求从中间件中直接放行了,只是使用 token 进行校验。因为我的这个项目目前是公司内部使用,安全性和性能之类的要求不高,暂时就只使用这种方式了。
至于其他下载方式的话,如果不想专门为了下载文件引入其他系统,那做到这样我觉得差不多了。如果真有特别强烈的需求,那针对文件存储下载单独写一个服务,再提供一个中间件可能更好一些,不过我觉得是没必要了。

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

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

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

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

© 2021 V2EX