用gin框架写一个大文件分块传输的完整代码
这里是一个使用gin框架实现的大文件分块传输的示例代码:
package main
import (
"fmt"
"io"
"log"
"net/http"
"os"
"strconv"
"github.com/gin-gonic/gin"
)
// 文件块大小,每块10M
const blockSize = 10 * 1024 * 1024
// 上传的文件对象
type File struct {
Name string
File *os.File
FileSize int64
Blocks int64
Done bool
}
// gin路由,所有请求都由此处理
func uploadFile(c *gin.Context) {
// 获取请求的参数
name := c.PostForm("name")
file, _ := c.FormFile("file")
size := file.Size
// 打开文件,准备上传
f, err := file.Open()
if err != nil {
log.Fatal(err)
}
defer f.Close()
saveFile, err := os.Create(file.Filename)
if err != nil {
log.Fatal(err)
}
defer saveFile.Close()
// 创建文件对象
uploadFile := &File{
Name: name,
File: saveFile,
FileSize: size,
Blocks: size / blockSize,
Done: false,
}
// 如果有上次未完成的上传,续传
blockStart := c.PostForm("blockStart")
blockEnd := c.PostForm("blockEnd")
if blockStart != "" {
start, _ := strconv.Atoi(blockStart)
end, _ := strconv.Atoi(blockEnd)
_, err = uploadFile.File.Seek(int64(start), 0)
if err != nil {
log.Fatal(err)
}
for i := start; i <= end; i++ {
uploadFile.Done = uploadBlock(f, uploadFile, i) == nil
}
}
// 如果不是续传,开始分块上传
if !uploadFile.Done {
for i := 0; i < int(uploadFile.Blocks); i++ {
err = uploadBlock(f, uploadFile, i)
if err != nil {
c.String(http.StatusBadRequest, fmt.Sprintf("upload block %d failed", i))
return
}
}
}
// 上传完成,返回成功
c.String(http.StatusOK, "file upload success")
}
// 上传单个文件块
func uploadBlock(file *os.File, uploadFile *File, blockNum int) error {
start := blockSize * blockNum
end := start + blockSize - 1
if end > uploadFile.FileSize - 1 {
end = uploadFile.FileSize - 1
}
buf := make([]byte, blockSize)
_, err := file.ReadAt(buf, int64(start))
if err != nil && err != io.EOF {
return err
}
_, err = uploadFile.File.WriteAt(buf, int64(start))
if err != nil {
return err
}
return nil
}
func main() {
r := gin.Default()
r.POST("/upload", uploadFile)
r.Run()
}
这个示例实现了大文件分块上传的主要逻辑:
- 定义文件块大小blockSize为10M
- 接收文件和名称,打开本地文件准备上传
- 创建文件对象,记录文件大小,块数等信息
- 如果有上次未完成的上传,根据块号续传未上传的部分
- 否则开始分块上传,逐个上传文件块
- 上传完成后返回成功
- uploadBlock函数负责上传单个文件块
这样就实现了大文件分块传输的功能。可以在界面上选择大文件进行上传,会自动进行分块传输。
网友评论