Output to csv file dumps the data to browser but not dump to file

1.9k views Asked by At

I tried to ouput some data to csv file in golang beego framework, here is my code

records := make([][]string,len(devicesData))

for k,v := range devicesData{
    records[k] = []string{v.Fields.Country,v.Fields.Imei[0],v.Fields.Number[0]}
}

writer := csv.NewWriter(this.Controller.Ctx.ResponseWriter)
for _, record := range records {
    err := writer.Write(record)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
}

this.Ctx.Output.Header("Content-Type", "application/csv")
this.Ctx.Output.Header("Content-Disposition", "attachment; filename=MyVerySpecial.csv")

    writer.Flush()

However, it only shows the record data in browser, it cannot download the file. I have some loging controller and filter function before this download file controller, I do not whether it is affected. What's wrong with my code? Thanks

1

There are 1 answers

0
icza On

You should always set response headers first and only after that start writing any data to the output. I know you called writer.Flush() after setting header fields, but that is no guarantee whatsoever that data will not be flushed or sent before that - which will imply default headers being sent. After this no additional headers can be sent or changed.

Also the proper mime type for CSV is text/csv not application/csv (rfc4180).

Also the headers are more like a "proposal" to the browser. That's one thing you suggest the response is a file to be saved, but from the server side you can't force the browser to really save the response to a file and not display it.

See rfc1806, rfc2183 and rfc6266 for more details about the "Content-Disposition" header field. Basically it communicates presentation information.

The Content-Disposition response header field is used to convey additional information about how to process the response payload, and also can be used to attach additional metadata, such as the filename to use when saving the response payload locally.