How to server a file from a handler in golang
Just use this function from gin.Context: https://godoc.org/github.com/gin-gonic/gin#Context.File
Something like this:
const DOWNLOADS_PATH = "downloads/"
ginRouter.GET("/download-user-file/:filename", func (ctx *gin.Context) {
fileName := ctx.Param("filename")
targetPath := filepath.Join(DOWNLOADS_PATH, fileName)
//This ckeck is for example, I not sure is it can prevent all possible filename attacks - will be much better if real filename will not come from user side. I not even tryed this code
if !strings.HasPrefix(filepath.Clean(targetPath), DOWNLOADS_PATH) {
ctx.String(403, "Look like you attacking me")
return
}
//Seems this headers needed for some browsers (for example without this headers Chrome will download files as txt)
ctx.Header("Content-Description", "File Transfer")
ctx.Header("Content-Transfer-Encoding", "binary")
ctx.Header("Content-Disposition", "attachment; filename="+fileName )
ctx.Header("Content-Type", "application/octet-stream")
ctx.File(targetPath)
})
Here is a complete working example using the standard http package. Please note, that the filename or path you use is relative to your current working directory.
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "file")
})
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
For more use Use directly use c.FileAttachment for example:-
func DownloadHandler(c *gin.Context) {
c.FileAttachment("./downloads/file.zip","filename.zip")
}