Home > Back-end >  Corrupted zip file is sent in golang REST API
Corrupted zip file is sent in golang REST API

Time:01-31

I've searched a lot about this issue, but I couldn't find a suitable solution. I want to find some records from a mongodb collection and save each record to a json file, then zip them and send back as the response of an REST API.

    // each record should be saved in a file
    var records []iodefRepo.IodefRecord
    if cur, err := h.iodefRepo.IodefCollection().Find(helper.Context(), filter, options.Find().SetSort(M{"received_at": -1})); err != nil {
        return helper.WrapInternalErr("while finding iodef, err="   err.Error())
    } else if err := cur.All(helper.Context(), &records); err != nil {
        return helper.WrapInternalErr("while un-cursoring records, err="   err.Error())
    }

    -------------------------------------------------------
    resultFile, err := os.Create(fmt.Sprint(fileName, ".zip"))
    if err != nil {
        return helper.WrapInternalErr("while creating the result file, err="   err.Error())
    }

    writer := zip.NewWriter(resultFile)
    // files is a [][]byte that each element is []byte of json.Unmarshal
    for i, f := range files {
        if file, err := writer.Create(fmt.Sprint("IncidentName=", records[i].Document.Incidents[0].IncidentID.Name, ", IncidentData=", records[i].Document.Incidents[0].IncidentID.Data, ".", format)); err != nil {
            return helper.WrapInternalErr("while creating iodef file, err="   err.Error())
        } else if _, err := file.Write(f); err != nil {
            return helper.WrapInternalErr("while writing to iodef file, err="   err.Error())
        }
    }

    helper.AddResponseHeader("Content-Type", "application/zip")
    helper.AddResponseHeader("Content-Transfer-Encoding", "binary")
    helper.AddResponseHeader("Content-Disposition", "attachment; filename=export.zip")

    _ = writer.Close()
    _ = resultFile.Close()

    if result, err := os.ReadFile(fileName   ".zip"); err != nil {
        return helper.WrapInternalErr("while reading zip file, err="   err.Error())
    } else {
        // this result which is a []byte will be write to standard ResponseWriter
        // the same as err := w.Write(result); mention that I have ckecked and there
        // is no error in any of the steps and everything is done without any errors.
        return helper.WrapOk(result)
    }
    

I save the zip file after generation on server and test it, it works completely fine but when I read the response in postman and save it as a zip, The file is corrupted, I don't know why and I don't have any clue to solve the issue, There are similar issues but none of them worked. Response of the API in postman is exactly the same size as file that has been generated on serverside.

I did try a few stuffs such as using different headers and different methods to read the result zip file, none of them worked, I think os.ReadFile is the best option to read a binary file completely. I do not have any clue of why this issue exists. Just want to emphasize, the generated zip file is working properly on serverside, after sending it as a binary array using os.ReadFile and standard http.ResponseWriter.Write, file won't work properly.

CodePudding user response:

Finally I found the answer, I still do not know what is wrong with my previous solution, but when I use http.ServeFile(w, r, "/path/to/zip_file") function instead of using ResponseWriter.Write(fileBytes), the problem solved. It is actually so strange that using ResponseWriter.Write(fileBytes) could cause the issue. If anyone have any idea of why that happens, let me know about it. Thanks.

  • Related