在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
}
}
}
关键说明:
- Content-Disposition:
attachment 强制浏览器下载而非预览
- Content-Type:
application/octet-stream 表示二进制流
- 错误处理:必须检查文件是否存在和可读
- 内存效率:大文件应使用流式传输避免内存过载
访问 http://localhost:8080/download 即可触发下载。根据文件大小选择合适的方法,小文件可用简单读取,大文件建议使用流式传输。