前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于一个打包下载的需求

关于一个打包下载的需求

作者头像
LA0WAN9
发布2022-09-02 11:40:34
4770
发布2022-09-02 11:40:34
举报
文章被收录于专栏:火丁笔记

前些天遇到一个「打包下载」的需求,在调研过程中走了一些弯路,本文记录一下。

比如说某网站有一个文件列表,用户点哪个就可以下载哪个,如果用户想下载多个,无非就是多点几次而已。于是需求来了:当用户想下载多个文件的时候,可以通过一次点击完成打包下载操作。

听起来似乎并不复杂,服务端可以把用户想要下载的文件打包成一个新文件,然后用户点一次就可以下载了,但是这样做有以下几个缺点:

  • 浪费了时间,多了创建新文件的流程。
  • 浪费了空间,同样的文件被多次存储。
  • 用户体验差,下载必须要等到新文件创建好才能开始。

不难得出结论:动态流式下载才是正解,同事提到 tar 可以搞定,于是研究一下:

代码语言:javascript
复制
shell> cat test_0.txt 
xxx
xxx
shell> cat test_1.txt 
yyy
yyy
shell> tar cf test.tar test_0.txt test_1.txt
shell> cat test.tar 
test_0.txt00006440...01014257504126011510 0ustar rootrootxxx
xxx
test_1.txt00006440...01014257504241011507 0ustar rootrootyyy
yyy

如上可见,tar 文件的格式非常简单,多个文件的内容从上到下依次排列,只不过每个文件内容的前面附加了一个头,其中保存了诸如文件名,权限之类的信息。

看上去用 tar 的话确实可以搞定动态流式下载,不过 tar 有个缺点,普通用户搞不清 tar 文件类型是什么东西,相比较而言,他们更乐于接受 zip 文件类型。

不过 zip 文件类型的格式可要比 tar 复杂,我从 wikipedia 找到下图:

zip
zip

zip

对于凡夫俗子的我来说,想要通过手撸 zip 格式来实现动态流式下载绝非易事,就在举棋不定之际,我突然发现 golang 的 zip 标准库已经实现了 Writer 接口,这就意味着,我们只要结合使用 zip.NewWriter 和 http.ResponseWriter 就能实现我们的目的:

代码语言:javascript
复制
package main

import (
	"archive/zip"
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	http.HandleFunc("/test", test)
	http.ListenAndServe(":8080", nil)
}

func test(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/zip")
	w.Header().Set("Content-Disposition", "attachment; filename=test.zip")
	writer := zip.NewWriter(w)
	for i := 0; i < 2; i++ {
		name := fmt.Sprintf("test_%d.txt", i)
		srcFile, err := os.Open(name)
		if err != nil {
			panic(err)
		}
		defer srcFile.Close()
		dstFile, err := writer.Create(name)
		if err != nil {
			panic(err)
		}
		if _, err := io.Copy(dstFile, srcFile); err != nil {
			panic(err)
		}
	}
	writer.Close()
}

如上代码编译运行后,打开浏览器,执行 http://localhost:8080/test 即可看到效果。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-07-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档