Issues sending compressed ZIP files using Gin framework

37 Views Asked by At

I'm working on a project using Golang and the Gin web framework, and I'm having trouble sending compressed zip files as a response. When I check locally created zip file and check its content, everything appears to be in order. However, when I save the file from the response using Postman, I encounter errors when trying to open it. Additionally, online decompressors reveal that there are no files inside the saved zip.

I suspect that the issue may be related to how I'm using ctx.File() in Gin. Here's the relevant code:

package archive_compress

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

        "github.com/gin-gonic/gin"
        "archiver/internal/dto"
        "archiver/internal/helpers/random"
    )



    const formKey = "files[]"
    const zipStoragePath = "archives/"

    func Compress(c *gin.Context) {

    form, err := c.MultipartForm()
    if err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": "there is no files in request"})
        return
    }
    files, ok := form.File[formKey]
    if !ok {
        c.JSON(http.StatusBadRequest, gin.H{"error": "there is no files in request"})
        return
    }

    randZipName := random.RandomZipFileName()
    filePath := zipStoragePath + randZipName
    zipFile, err := os.Create(filePath)
    if err != nil {
        c.JSON(http.StatusInternalServerError, err)
        return
    }
    defer zipFile.Close()

    zipFile.Chmod(os.FileMode(0666))

    zipWriter := zip.NewWriter(zipFile)
    defer zipWriter.Close()
    for _, fileHeader := range files {
        file, err := fileHeader.Open()
        if err != nil {
            c.JSON(http.StatusInternalServerError, err)
            return
        }
        defer file.Close()

        // f := &zip.FileHeader{Name: fileHeader.Filename, Method: zip.Deflate}
        createdDest, err := zipWriter.Create(fileHeader.Filename)
        if err != nil {
            c.JSON(http.StatusInternalServerError, err)
            return
        }

        _, err = io.Copy(createdDest, file)
        if err != nil {
            c.JSON(http.StatusInternalServerError, err)
            return
        }

    }

    fileInfo, err := zipFile.Stat()
    if err != nil {
        log.Fatal(err)
    }

    disposition := fmt.Sprintf("attachment; filename=%s", fileInfo.Name())
    c.Writer.Header().Set("Content-Type", "application/zip")
    c.Writer.Header().Set("Content-Disposition", disposition)
    // c.Writer.Header().Set("Content-Length", fmt.Sprintf("%d", fileInfo.Size()-int64(100000)))

    c.File(filePath)
    // c.FileAttachment(filePath, fileInfo.Name())

}

I'd appreciate any guidance on how to correctly compress files and send them as a response in a way that ensures the zip files are valid and can be opened without issues. Are there any specific considerations or techniques I should be aware of when working with zip files and Gin in Golang?

Additional Information:

Golang version: 1.20
Gin version: 1.9.1
0

There are 0 best solutions below