需求背景:用户勾选多张图片进行下载,需要将多张图片打成一个zip包进行返回
参考:https://studygolang.com/articles/9659
上代码:
func DownloadFiles(c *ginserver.Context) (resp interface{}, e error) {
//获取url中的参数:ids
param := c.Query("ids")
//类型转换,string转int
array := strings.Split(param, ",")
ids := make([]int, len(array))
for i, str := range array {
id, _ := strconv.Atoi(str)
ids[i] = id
}
//获取当前时间作为新建的zip包名(固定写法)
fileName := time.Now().Format("2006-01-02 15:04:05") + ".zip"
//设置响应头
c.Writer.Header().Add("Content-Disposition", "attachment; filename=\""+fileName+"\"")
c.Writer.Header().Add("Content-Type", "application/zip")
err := GetZip(c, c.Writer, ids)
if err != nil {
log.Fatal(err)
}
return
}
//获取zip流
func GetZip(ctx context.Context, rw io.Writer, ids []int) error {
//这里我是根据业务需求直接在库里进行查询的
element := dao.Element{DB: config.DB.WithContext(ctx)}
elements := make([]entity.Element, len(ids))
elements, err := element.GetElementsByIds(ids)
if len(elements) == 0 {
return err
}
//在流中创建一个 zipwriter
zipwriter := zip.NewWriter(rw)
//关闭zipwriter
defer zipwriter.Close()
//循环写入图片
for _, f := range elements {
iowriter, err := zipwriter.Create(f.Name)
if err != nil {
return err
}
var content []byte
resp, err := http.Get(f.Url)
if err == nil {
content, err = ioutil.ReadAll(resp.Body)
if err != nil {
content = []byte("")
}
resp.Body.Close()
}
iowriter.Write(content)
}
return nil
}
注意:
1.一般下载文件都会使用GET方法来请求,这个好像是跟前端有关系,具体的参见:http://ishare.iask.sina.com.cn/f/bsyG3SeC4EJ.html
2.设置响应头,这一步很关键,Content-Type可以根据具体的文件类型来进行选择,Content-Disposition于告知浏览器其获取到的文件是需要展示与页面内还是需要作为附件保存到用户本地,如果需要展示在页面内,设置为inline,否则设置为attachemn