golang怎么实现大文件传输和断点续传

avatar
作者
猴君
阅读量:3

在Golang中,可以使用HTTP协议来实现大文件传输和断点续传。下面是一个简单的示例代码:

package main  import ( 	"fmt" 	"io" 	"net/http" 	"os" 	"strconv" )  func handler(w http.ResponseWriter, r *http.Request) { 	file, err := os.Open("large_file.txt") 	if err != nil { 		fmt.Println("Error opening file: ", err) 		return 	} 	defer file.Close()  	fileInfo, err := file.Stat() 	if err != nil { 		fmt.Println("Error getting file info: ", err) 		return 	}  	w.Header().Set("Content-Disposition", "attachment; filename=large_file.txt") 	w.Header().Set("Content-Type", "application/octet-stream") 	w.Header().Set("Content-Length", strconv.FormatInt(fileInfo.Size(), 10))  	http.ServeContent(w, r, "large_file.txt", fileInfo.ModTime(), file) }  func main() { 	http.HandleFunc("/", handler) 	http.ListenAndServe(":8080", nil) } 

在上面的示例中,我们首先打开了一个名为large_file.txt的大文件,并设置了HTTP响应头,然后使用http.ServeContent函数将文件内容发送给客户端。客户端可以通过访问http://localhost:8080来下载这个大文件。

如果要实现断点续传功能,可以通过检查HTTP请求的Range头来决定从文件的哪个位置开始传输。以下是一个修改后的示例代码:

func handler(w http.ResponseWriter, r *http.Request) { 	file, err := os.Open("large_file.txt") 	if err != nil { 		fmt.Println("Error opening file: ", err) 		return 	} 	defer file.Close()  	fileInfo, err := file.Stat() 	if err != nil { 		fmt.Println("Error getting file info: ", err) 		return 	}  	w.Header().Set("Content-Disposition", "attachment; filename=large_file.txt") 	w.Header().Set("Content-Type", "application/octet-stream") 	w.Header().Set("Content-Length", strconv.FormatInt(fileInfo.Size(), 10))  	rangeHeader := r.Header.Get("Range") 	if rangeHeader != "" { 		startRange, endRange, err := parseRangeHeader(rangeHeader, fileInfo.Size()) 		if err != nil { 			fmt.Println("Error parsing range header: ", err) 			return 		} 		w.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", startRange, endRange, fileInfo.Size())) 		http.ServeContent(w, r, "large_file.txt", fileInfo.ModTime(), io.NewSectionReader(file, startRange, endRange-startRange+1)) 	} else { 		http.ServeContent(w, r, "large_file.txt", fileInfo.ModTime(), file) 	} }  func parseRangeHeader(rangeHeader string, fileSize int64) (int64, int64, error) { 	prefix := "bytes=" 	if len(rangeHeader) < len(prefix) || rangeHeader[:len(prefix)] != prefix { 		return 0, 0, fmt.Errorf("Invalid range header format") 	} 	rangeStr := rangeHeader[len(prefix):]  	dashIndex := strings.IndexByte(rangeStr, '-') 	if dashIndex == -1 { 		return 0, 0, fmt.Errorf("Invalid range header format") 	}  	startRange, err := strconv.ParseInt(rangeStr[:dashIndex], 10, 64) 	if err != nil { 		return 0, 0, err 	}  	endRangeStr := rangeStr[dashIndex+1:] 	var endRange int64 	if endRangeStr == "" { 		endRange = fileSize - 1 	} else { 		endRange, err = strconv.ParseInt(endRangeStr, 10, 64) 		if err != nil { 			return 0, 0, err 		} 	}  	return startRange, endRange, nil } 

在上面的修改后的示例代码中,我们首先解析了HTTP请求的Range头,然后根据请求的范围读取文件内容,并设置Content-Range头告知客户端传输的内容范围。

通过这种方式,我们可以实现大文件传输和断点续传的功能。在实际应用中,可以根据需要对代码进行进一步的优化和扩展。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!