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
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
notapplication/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.