/* Copyright (c) [2023] [pcm] [pcm-coordinator] is licensed under Mulan PSL v2. You can use this software according to the terms and conditions of the Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPaRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. */ package image import ( "bufio" "fmt" "github.com/zeromicro/go-zero/core/logx" "gitlink.org.cn/jcce-pcm/pcm-coordinator/api/internal/svc" "gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/repository/result" "gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/utils/fileutils" "io" "net/http" "os" "path/filepath" "strconv" "syscall" ) type LoadBody struct { Stream string `json:"stream"` } var uploadTempPath = filepath.Join(uploadPath, "temp") func UploadHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { file, fileHeader, err := r.FormFile("file") if err != nil { logx.Error(err) result.HttpResult(r, w, nil, err) return } index := r.PostFormValue("index") hash := r.PostFormValue("hash") defer file.Close() // 合并路径 chunksPath := filepath.Join(uploadTempPath, hash) // 文件路径 filePath := filepath.Join(chunksPath, hash+"-"+index) // 检查临时文件夹是否存在 不存在则创建文件夹 isPathExists, err := fileutils.PathExists(chunksPath) if !isPathExists { err = os.MkdirAll(chunksPath, os.ModePerm) if err != nil { logx.Error(err) result.HttpResult(r, w, nil, err) return } } // 检查文件是否存在 exists, err := fileutils.PathExists(filePath) if err != nil { logx.Error(err) result.HttpResult(r, w, nil, err) return } // 文件存在 进行断点续传 if exists { fileInfo, _ := os.Stat(filePath) if fileInfo.Size() == fileHeader.Size { result.HttpResult(r, w, nil, err) return } start := strconv.Itoa(int(fileInfo.Size())) oldFile, _ := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY, os.ModePerm) defer oldFile.Close() count, _ := strconv.ParseInt(start, 10, 64) fmt.Println("已上传:", count) // 设置读,写的偏移量 file.Seek(count, 0) oldFile.Seek(count, 0) data := make([]byte, 1024, 1024) for { total, err := file.Read(data) if err == io.EOF { fmt.Println("文件复制完毕") break } oldFile.Write(data[:total]) } // 文件不存在 直接上传 } else { destFile, _ := os.OpenFile(filepath.Join(chunksPath, hash+"-"+index), syscall.O_CREAT|syscall.O_WRONLY, 0777) reader := bufio.NewReader(file) writer := bufio.NewWriter(destFile) buf := make([]byte, 1024*1024) // 1M buf for { n, err := reader.Read(buf) if err == io.EOF { writer.Flush() break } else if err != nil { return } else { writer.Write(buf[:n]) } } defer file.Close() defer destFile.Close() } result.HttpResult(r, w, nil, err) } }