golang - 如何从golang服务器下载浏览器中的文件?

lei*_*lin 26 go

我的代码从远程URL获取文件并在浏览器中下载文件:

func Index(w http.ResponseWriter, r *http.Request) {
    url := "http://upload.wikimedia.org/wikipedia/en/b/bc/Wiki.png"

    ...

    resp, err := client.Get(url)
    if err != nil {
        fmt.Println(err)
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Println(len(body))
    //download the file in browser

}

func main() {
    http.HandleFunc("/", Index)
    err := http.ListenAndServe(":8000", nil)

    if err != nil {
        fmt.Println(err)
    }
}
Run Code Online (Sandbox Code Playgroud)

代码:http://play.golang.org/p/x-EyR2zFjv

获取文件是可以的,但如何在浏览器中下载?

谢谢.

Not*_*fer 59

要使浏览器打开下载对话框,请在响应中添加一个Content-DispositionContent-Type标题:

w.Header().Set("Content-Disposition", "attachment; filename=WHATEVER_YOU_WANT")
w.Header().Set("Content-Type", r.Header.Get("Content-Type"))
Run Code Online (Sandbox Code Playgroud)

在将内容发送到客户端之前执行此操作.您可能还希望将Content-Length响应的标头复制到客户端,以显示正确的进度.

要将响应主体流式传输到客户端而不将其完全加载到内存中(对于大文件这很重要) - 只需将主体读取器复制到响应编写器:

io.Copy(w, resp.Body)
Run Code Online (Sandbox Code Playgroud)

io.Copy是一个很好的小函数,它采用读取器接口和编写器接口,从一个读取数据并将其写入另一个.对这种东西非常有用!

我修改了你的代码来做到这一点:http://play.golang.org/p/v9IAu2Xu3_

  • 如果文件名中有空格,请确保用引号括起filename = arg,例如`filename ="WHATEVER YOU WANT"`. (7认同)
  • 我认为它应该是 `resp` 而不是 `r` --------> `w.Header().Set("Content-Type", resp.Header.Get("Content-Type")) ` 和 `w.Header().Set("Content-Length", fmt.Sprintf("%d", resp.ContentLength))` (2认同)

Nin*_*ham 7

如果您已经在磁盘上有该文件,只需使用http.ServeFile()。它会自动处理Content-Length以便浏览器可以显示下载进度。

w.Header().Set("Content-Disposition", "attachment; filename="+strconv.Quote(filename))
w.Header().Set("Content-Type", "application/octet-stream")
http.ServeFile(w, r, filePath)
Run Code Online (Sandbox Code Playgroud)