如何在 Go 语言中实现一个支持大文件上传并显示进度条的客户端?
时间: 2024-12-18 07:35:30 浏览: 4
在Go语言中,你可以使用标准库`net/http`处理HTTP请求,并结合`io`和`context`包来实现实现大文件上传以及进度跟踪。下面是一个简单的示例,展示了如何创建一个支持大文件上传的客户端,同时提供了一个基础的进度条:
```go
package main
import (
"context"
"fmt"
"io"
"net/http"
"os"
"mime/multipart"
"strings"
)
func uploadFile(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" || r.Header.Get("Content-Type") != "multipart/form-data" {
http.Error(w, "Invalid request method or content type", http.StatusBadRequest)
return
}
file, header, err := r.FormFile("file")
if err != nil {
http.Error(w, "Failed to read file", http.StatusInternalServerError)
return
}
defer file.Close()
progressCh := make(chan int64, 1024) // 假设每1K更新一次进度
go handleUploadProgress(file, progressCh, w)
body, err := io.ReadAll(file)
if err != nil {
http.Error(w, "Failed to read file body", http.StatusInternalServerError)
return
}
err = saveToDisk(header.Filename, body)
if err != nil {
http.Error(w, "Failed to save to disk", http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "File uploaded successfully.\n")
}
func handleUploadProgress(r io.ReaderAt, ch chan<- int64, w http.ResponseWriter) {
var totalSize int64
buf := make([]byte, 512)
for {
n, _ := r.ReadAt(buf, 0)
totalSize += n
ch <- totalSize
if n < len(buf) {
break
}
}
// 更新进度条,这里只是一个简化的例子,可以根据实际情况调整
fmt.Fprintf(w, "Uploading %s...%s\n", header.Filename, humanize.Bytes(totalSize))
}
// 这里假设saveToDisk函数将数据保存到本地磁盘
func saveToDisk(filename string, data []byte) error {
// 实际操作,如创建目录、写入文件等...
}
func humanizeBytes(size uint64) string {
// 返回以KB、MB、GB为单位的字符串表示
}
func main() {
http.HandleFunc("/upload", uploadFile)
http.ListenAndServe(":8080", nil)
}
```
在这个示例中,`handleUploadProgress`函数会异步读取文件内容并在接收到每个块后发送进度更新到`progressCh`通道。在服务器端,`uploadFile`函数接收文件上传请求,然后读取文件并分块处理,同时通过`w`向用户展示进度。
请注意,这只是一个基础的框架,实际应用中可能需要添加错误处理、异常终止上传、以及更复杂的进度显示机制,例如使用`goroutine`并发读取文件以提高性能。此外,`humanizeBytes`函数用于将字节数转换成友好的人类可读格式。
阅读全文