Search code examples
jsongogo-gin

How to write a GET endpoint in Gin that lets the user download a file + metadata in json format?


I have created an endpoint that allows users to upload a file + metadata in json format and I store them but I have some problems creating a GET endpoint that allows a user to download the file and metadata in json format in one call.

I wrote below code that returns the json metadata + file BUT the json is added at the beginning of the file and not as a separate object:

jsonData, err := json.Marshal(metadata)
// Set the response headers
c.Header("Content-Disposition", "attachment; filename=file.md")
c.Header("Content-Type", "application/octet-stream")

// Write the file contents and JSON data to the response body
c.Writer.Write(jsonData)
c.Writer.Write(file)

How can I solve this issue?


Solution

  • Using the https://stackoverflow.com/users/5027489/whitesword hint I rewrite my code to use multipart/form-data and that solved the problem:

            // Set the response headers
            c.Header("Content-Disposition", "attachment; filename=file.md")
            c.Header("Content-Type", "multipart/form-data")
    
            // Create a multipart response writer
            writer := multipart.NewWriter(c.Writer)
            defer writer.Close()
    
            // Add the file to the response
            fileWriter, err := writer.CreateFormFile("file", "file.md")
            if err != nil {
                c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create form file"})
                return
            }
            fileWriter.Write(file)
    
            // Add the JSON data to the response
            jsonWriter, err := writer.CreateFormField("metadata")
            if err != nil {
                c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create form field"})
                return
            }
            jsonWriter.Write(jsonData)
    
            // Complete the multipart response
            c.Writer.Header().Set("Content-Type", writer.FormDataContentType())
    
            // Return the response
            c.Writer.WriteHeader(http.StatusOK)