如何使用 Gin 在 HTTP 服务器中动态生成 zip/7z 存档?

Ser*_*gey 3 zip archive go httpserver

我使用Gin创建了一个 HTTP 服务器,我想为用户提供一个动态生成的 zip 存档。

理论上我可以先在文件系统上生成一个 zip 文件,然后再提供它。但这确实是一种糟糕的方式(在开始下载之前等待 5 分钟)。我想立即开始将其提供给用户并在生成时推送内容。

我找到了 DataFromReader(示例),但在存档完成之前不知道 ContentLength。

func DownloadEndpoint(c *gin.Context) {
    ...
    c.DataFromReader(
        http.StatusOK,
        ContentLength,
        ContentType,
        Body,
        map[string]string{
            "Content-Disposition": "attachment; filename=\"archive.zip\""),
        },
    )
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

edk*_*ked 6

使用流方法存档/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()
}
Run Code Online (Sandbox Code Playgroud)

通过直接使用 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()
}
Run Code Online (Sandbox Code Playgroud)