package service import ( "basic.com/valib/logger.git" "bufio" "fmt" "io/ioutil" "mime/multipart" "os" "os/exec" "strconv" "strings" "webserver/extend/config" "webserver/extend/util" ) type SysService struct { } type FileChunkCheckVo struct { UserId string ChunkNumber int //当前分片下标,从1开始 ChunkSize int //每一块的大小 CurrentChunkSize int //当前分块的大小 FileName string //文件名称 Identifier string //整个文件唯一标识,md5 RelativePath string //文件客户端路径 TotalSize int64 //文件总大小 TotalChunks int //总分片数量 } type FileUploadVo struct { Id string UserId string ChunkNumber int //当前分片下标,从1开始 ChunkSize int //每一块的大小 CurrentChunkSize int //当前分块的大小 FileName string //文件名称 Identifier string //整个文件唯一标识,md5 RelativePath string //文件客户端路径 TotalSize int64 //文件总大小 TotalChunks int //总分片数量 File *multipart.File //当前分片的文件内容 Header *multipart.FileHeader } func (sv SysService) CheckUpdateFile(arg *FileChunkCheckVo) bool { configPatchPath := "" if config.Server.PatchPath != "" { configPatchPath = config.Server.PatchPath } else { configPatchPath = "/opt/vasystem/patch" } fileTmpPath := configPatchPath + "/"+arg.Identifier if !util.Exists(fileTmpPath) { return false } //判断合成的文件是否存在 index := strings.LastIndex(arg.FileName, ".") subfix := "" if index >-1 {//有后缀 subfix = arg.FileName[index:] } mergedFilePath := fileTmpPath+subfix if util.Exists(mergedFilePath) { return true } //判断分块文件是否存在 chunkFilePath := fileTmpPath+"/"+arg.Identifier+"_"+strconv.Itoa(arg.ChunkNumber) if !util.Exists(chunkFilePath) { return false } if arg.ChunkNumber == arg.TotalChunks { dirFiles, _ := ioutil.ReadDir(fileTmpPath) if dirFiles != nil && len(dirFiles) == arg.TotalChunks { //表示所有分块都上传了,需要merge if sv.MergeChunks(fileTmpPath, mergedFilePath) { if util.ZipCheck(mergedFilePath) { if !updatePatch(arg.Identifier, subfix) { return false } } } } } return true } func (sv SysService) PatchUpload(arg *FileUploadVo) bool { configPatchPath := "" if config.Server.PatchPath != "" { configPatchPath = config.Server.PatchPath } else { configPatchPath = "/opt/vasystem/patch" } defer (*arg.File).Close() if !util.CreateDirectory(configPatchPath) { return false } index := strings.LastIndex(arg.Header.Filename, ".") if index < 0 { return false } subfix := arg.Header.Filename[index:] MD5Str := arg.Identifier logger.Debug("Identifier:",MD5Str) fileTmpPath := configPatchPath + "/"+MD5Str if !util.Exists(fileTmpPath) { if !util.CreateDirectory(fileTmpPath) { return false } } fileSavePath := fileTmpPath+"/"+MD5Str+"_"+strconv.Itoa(arg.ChunkNumber) if util.Exists(fileSavePath) { rmErr := os.Remove(fileSavePath) if rmErr != nil { logger.Debug("rmErr:",rmErr) return false } } file, e := os.Create(fileSavePath) if e !=nil { logger.Debug("os.Create err:",e,"fileSavePath:",fileSavePath) return false } defer file.Close() writer := bufio.NewWriter(file) chunkData := make([]byte, arg.Header.Size) n, err := (*arg.File).ReadAt(chunkData, 0) if n ==0 || err !=nil { logger.Debug("read chunkData err:",err,"n:",n) return false } nn, err2 := writer.Write(chunkData) if nn ==0 || err2 !=nil { logger.Debug("write chunkData err:",err2,"nn:",nn) return false } isComplete := false dirFiles, _ := ioutil.ReadDir(fileTmpPath) if dirFiles != nil && len(dirFiles) == arg.TotalChunks { isComplete = true } if isComplete { if sv.MergeChunks(fileTmpPath,fileTmpPath + subfix) { logger.Debug("merge all chunks success,identifier:",MD5Str,"fileName:",arg.FileName) if util.ZipCheck(fileTmpPath + subfix) { if !updatePatch(arg.Identifier, subfix) { return false } } } } return true } //更新系统程序 func updatePatch(identifier string, ext string) bool { configPatchPath := "" if config.Server.PatchPath != "" { configPatchPath = config.Server.PatchPath } else { configPatchPath = "/opt/vasystem/patch" } //1.解压缩更新包 unZipPath := configPatchPath+"/"+identifier+"_basic/" if util.Exists(unZipPath) { //此版本已经更新过 return true } else { if !util.CreateDirectory(unZipPath) { return false } } err := util.UnZip(configPatchPath+"/"+identifier+ext, unZipPath) if err !=nil { logger.Debug("UnZip err:",err,"zipFile:",configPatchPath+"/"+identifier+ext) return false } //2.更新系统 var cmd *exec.Cmd updateCmd := fmt.Sprintf("setsid updatePatch.sh %s",unZipPath) cmd = exec.Command("/bin/sh","-c", updateCmd) logger.Debug("called sh updatePatch.sh,updateCmd:",updateCmd) if b, err := cmd.Output(); err != nil { logger.Debug("updatePatch err:",err,"result:",string(b)) return false } return true } func (sv SysService) MergeChunks(chunkPath string, storePath string) bool { var cmd *exec.Cmd cmd = exec.Command("/bin/sh", "-c", fmt.Sprintf("./mergeAll.sh %s %s", chunkPath, storePath)) logger.Debug("called sh mergeAll.sh ", chunkPath, storePath) if b, err := cmd.Output(); err != nil { logger.Debug("mergeChunks err:", err, "result:", string(b)) return false } else { return true } }