Golang文件下载实现

在Golang中如何实现文件下载功能?想了解如何通过HTTP服务让客户端下载服务器上的文件,包括设置正确的Content-Type和Content-Disposition头信息,以及处理大文件的分块传输。能否提供完整的代码示例和最佳实践?

2 回复

使用Golang实现文件下载,可通过HTTP服务器设置响应头实现:

http.HandleFunc("/download", func(w http.ResponseWriter, r *http.Request) {
    filePath := "path/to/file.zip"
    w.Header().Set("Content-Disposition", "attachment; filename=file.zip")
    w.Header().Set("Content-Type", "application/octet-stream")
    http.ServeFile(w, r, filePath)
})

关键点:

  • 设置Content-Disposition头为attachment
  • 使用http.ServeFile高效传输文件
  • 支持大文件流式传输

更多关于Golang文件下载实现的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang中实现文件下载,可以通过HTTP服务器将文件发送给客户端。以下是几种常见的方法:

1. 基础文件下载

package main

import (
    "net/http"
    "os"
    "path/filepath"
)

func downloadHandler(w http.ResponseWriter, r *http.Request) {
    filePath := "./files/sample.pdf"
    
    // 打开文件
    file, err := os.Open(filePath)
    if err != nil {
        http.Error(w, "文件未找到", http.StatusNotFound)
        return
    }
    defer file.Close()

    // 获取文件信息
    fileInfo, err := file.Stat()
    if err != nil {
        http.Error(w, "无法读取文件信息", http.StatusInternalServerError)
        return
    }

    // 设置响应头
    w.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(filePath))
    w.Header().Set("Content-Type", "application/octet-stream")
    w.Header().Set("Content-Length", string(fileInfo.Size()))

    // 发送文件内容
    http.ServeContent(w, r, fileInfo.Name(), fileInfo.ModTime(), file)
}

func main() {
    http.HandleFunc("/download", downloadHandler)
    http.ListenAndServe(":8080", nil)
}

2. 使用ioutil读取文件(适用于小文件)

func downloadHandler(w http.ResponseWriter, r *http.Request) {
    filePath := "./files/sample.pdf"
    
    data, err := os.ReadFile(filePath)
    if err != nil {
        http.Error(w, "文件未找到", http.StatusNotFound)
        return
    }

    w.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(filePath))
    w.Header().Set("Content-Type", "application/octet-stream")
    w.Header().Set("Content-Length", string(len(data)))
    
    w.Write(data)
}

3. 流式传输(适用于大文件)

func downloadHandler(w http.ResponseWriter, r *http.Request) {
    filePath := "./files/largefile.zip"
    
    file, err := os.Open(filePath)
    if err != nil {
        http.Error(w, "文件未找到", http.StatusNotFound)
        return
    }
    defer file.Close()

    fileInfo, err := file.Stat()
    if err != nil {
        http.Error(w, "无法读取文件信息", http.StatusInternalServerError)
        return
    }

    w.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(filePath))
    w.Header().Set("Content-Type", "application/octet-stream")
    w.Header().Set("Content-Length", string(fileInfo.Size()))

    // 使用缓冲区流式传输
    buffer := make([]byte, 4096)
    for {
        n, err := file.Read(buffer)
        if err != nil && err != io.EOF {
            http.Error(w, "读取文件出错", http.StatusInternalServerError)
            return
        }
        if n == 0 {
            break
        }
        if _, err := w.Write(buffer[:n]); err != nil {
            return
        }
    }
}

关键说明:

  1. Content-Dispositionattachment 强制浏览器下载而非预览
  2. Content-Typeapplication/octet-stream 表示二进制流
  3. 错误处理:必须检查文件是否存在和可读
  4. 内存效率:大文件应使用流式传输避免内存过载

访问 http://localhost:8080/download 即可触发下载。根据文件大小选择合适的方法,小文件可用简单读取,大文件建议使用流式传输。

回到顶部