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