如何使用 Gin 在 HTTP 服务器中动态生成 zip/7z 存档?
Posted
技术标签:
【中文标题】如何使用 Gin 在 HTTP 服务器中动态生成 zip/7z 存档?【英文标题】:How to generate zip / 7z archive on the fly in a HTTP server using Gin? 【发布时间】:2019-08-09 11:37:23 【问题描述】:我使用Gin创建一个HTTP服务器,我想给用户一个动态生成的压缩包。
理论上,我可以先在文件系统上生成一个 zip 文件,然后再提供它。但这确实是一个糟糕的方法(在开始下载前等待 5 分钟)。我想立即开始将其提供给用户并在生成内容时推送内容。
我找到了 DataFromReader (example),但在存档完成之前无法知道 ContentLength。
func DownloadEndpoint(c *gin.Context)
...
c.DataFromReader(
http.StatusOK,
ContentLength,
ContentType,
Body,
map[string]string
"Content-Disposition": "attachment; filename=\"archive.zip\""),
,
)
我该怎么做?
【问题讨论】:
直接使用Stream method或ResponseWriter。 【参考方案1】:使用stream method 和archive/zip,您可以动态创建zip 并将它们流式传输到服务器。
package main
import (
"os"
"archive/zip"
"github.com/gin-gonic/gin"
)
func main()
r := gin.Default()
r.GET("/", func(c *gin.Context)
c.Writer.Header().Set("Content-type", "application/octet-stream")
c.Stream(func(w io.Writer) bool
// Create a zip archive.
ar := zip.NewWriter(w)
file1, _ := os.Open("filename1")
file2, _ := os.Open("filename2")
c.Writer.Header().Set("Content-Disposition", "attachment; filename='filename.zip'")
f1, _ := ar.Create("filename1")
io.Copy(f1, file1)
f2, _ := ar.Create("filename2")
io.Copy(f2, file2)
ar.Close()
return false
)
)
r.Run()
直接使用ResponseWriter
package main
import (
"io"
"os"
"archive/zip"
"github.com/gin-gonic/gin"
)
func main()
r := gin.Default()
r.GET("/", func(c *gin.Context)
c.Writer.Header().Set("Content-type", "application/octet-stream")
c.Writer.Header().Set("Content-Disposition", "attachment; filename='filename.zip'")
ar := zip.NewWriter(c.Writer)
file1, _ := os.Open("filename1")
file2, _ := os.Open("filename2")
f1, _ := ar.Create("filename1")
io.Copy(f1, file1)
f2, _ := ar.Create("filename1")
io.Copy(f1, file2)
ar.Close()
)
r.Run()
【讨论】:
既然可以将 zip 写入w
,为什么还要将其写入缓冲区?
正如@MarkusWMahlberg 所说,您应该将zip.NewWriter
调用移至函数闭包内,并将其直接转到w
,而无需创建或使用bytes.Buffer
或调用最终的io.Copy
.他们以这种方式拥有它,因为在将任何内容写入 HTTP 连接之前,压缩已在内存中完全完成,因此流式传输毫无意义。
使用流闭包提供的io.writer
来创建zip存档是有意义的
对我来说很好用,谢谢!顺便说一句,代码有一个小错误,我认为我们应该使用filename=\"filename.zip\"
而不是filename='filename.zip'
。以上是关于如何使用 Gin 在 HTTP 服务器中动态生成 zip/7z 存档?的主要内容,如果未能解决你的问题,请参考以下文章