How to server a file from a handler in golang

huangapple go评论78阅读模式
英文:

How to server a file from a handler in golang

问题

我想知道如何从处理程序中提供文件。我正在使用gogin,我尝试了以下方法。

func DownloadHandler(c *gin.Context) {
   c.File("./downloads/file.zip")
}

func DownloadConfigs(c *gin.Context) {
   http.ServeFile(c.Writer, c.Request, "./downloads/file.zip")
}

这两种解决方案都试过了,包括没有点的路径。

我对任何解决方案都持开放态度,因为gin与标准的http库兼容,所以我也可以使用非gin特定的解决方案。

英文:

I was wondering how to serve a file from a handler. I'm using go and gin and I've tried to do.

func DownloadHandler(c *gin.Context) {
   c.File("./downloads/file.zip")
}

and

func DownloadConfigs(c *gin.Context) {
   http.ServeFile(c.Writer, c.Request, "./downloads/file.zip")
}

and both of those solutions without the dot as well.

I'm open to any solution and because gin is compatible with the standard http lib, I can use non-gin specific solutions as well

答案1

得分: 17

这是一个使用标准http包的完整工作示例。请注意,您使用的文件名或路径是相对于当前工作目录的。

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)
    }
}
英文:

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)
    }
}

答案2

得分: 8

只需使用gin.Context中的这个函数:
https://godoc.org/github.com/gin-gonic/gin#Context.File

类似这样的代码:

const DOWNLOADS_PATH = "downloads/"

ginRouter.GET("/download-user-file/:filename", func (ctx *gin.Context) {
    fileName := ctx.Param("filename")
    targetPath := filepath.Join(DOWNLOADS_PATH, fileName)
    //这个检查只是一个示例,我不确定它是否可以防止所有可能的文件名攻击-如果真实的文件名不来自用户端,那将会更好。我甚至没有尝试过这段代码
    if !strings.HasPrefix(filepath.Clean(targetPath), DOWNLOADS_PATH) {
        ctx.String(403, "看起来你在攻击我")
        return
    }
    //似乎这些头部信息对于某些浏览器是必需的(例如,没有这些头部信息,Chrome会将文件下载为txt)
    ctx.Header("Content-Description", "文件传输")
    ctx.Header("Content-Transfer-Encoding", "binary")
    ctx.Header("Content-Disposition", "attachment; filename="+fileName )
    ctx.Header("Content-Type", "application/octet-stream")
    ctx.File(targetPath)
})
英文:

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)
})

答案3

得分: 4

以下是要翻译的内容:

更多用法可以直接使用c.FileAttachment,例如:

func DownloadHandler(c *gin.Context) {
    c.FileAttachment("./downloads/file.zip", "filename.zip")
}
英文:

For more use Use directly use c.FileAttachment for example:-

func DownloadHandler(c *gin.Context) {
     c.FileAttachment("./downloads/file.zip","filename.zip")
}

huangapple
  • 本文由 发表于 2015年7月26日 22:58:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/31638447.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定