github.com/cloudreve/Cloudreve/v3@v3.0.0-20240224133659-3edb00a6484c/pkg/task/compress.go (about) 1 package task 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "os" 8 "path/filepath" 9 "time" 10 11 model "github.com/cloudreve/Cloudreve/v3/models" 12 "github.com/cloudreve/Cloudreve/v3/pkg/filesystem" 13 "github.com/cloudreve/Cloudreve/v3/pkg/util" 14 ) 15 16 // CompressTask 文件压缩任务 17 type CompressTask struct { 18 User *model.User 19 TaskModel *model.Task 20 TaskProps CompressProps 21 Err *JobError 22 23 zipPath string 24 } 25 26 // CompressProps 压缩任务属性 27 type CompressProps struct { 28 Dirs []uint `json:"dirs"` 29 Files []uint `json:"files"` 30 Dst string `json:"dst"` 31 } 32 33 // Props 获取任务属性 34 func (job *CompressTask) Props() string { 35 res, _ := json.Marshal(job.TaskProps) 36 return string(res) 37 } 38 39 // Type 获取任务状态 40 func (job *CompressTask) Type() int { 41 return CompressTaskType 42 } 43 44 // Creator 获取创建者ID 45 func (job *CompressTask) Creator() uint { 46 return job.User.ID 47 } 48 49 // Model 获取任务的数据库模型 50 func (job *CompressTask) Model() *model.Task { 51 return job.TaskModel 52 } 53 54 // SetStatus 设定状态 55 func (job *CompressTask) SetStatus(status int) { 56 job.TaskModel.SetStatus(status) 57 } 58 59 // SetError 设定任务失败信息 60 func (job *CompressTask) SetError(err *JobError) { 61 job.Err = err 62 res, _ := json.Marshal(job.Err) 63 job.TaskModel.SetError(string(res)) 64 65 // 删除压缩文件 66 job.removeZipFile() 67 } 68 69 func (job *CompressTask) removeZipFile() { 70 if job.zipPath != "" { 71 if err := os.Remove(job.zipPath); err != nil { 72 util.Log().Warning("Failed to delete temp zip file %q: %s", job.zipPath, err) 73 } 74 } 75 } 76 77 // SetErrorMsg 设定任务失败信息 78 func (job *CompressTask) SetErrorMsg(msg string) { 79 job.SetError(&JobError{Msg: msg}) 80 } 81 82 // GetError 返回任务失败信息 83 func (job *CompressTask) GetError() *JobError { 84 return job.Err 85 } 86 87 // Do 开始执行任务 88 func (job *CompressTask) Do() { 89 // 创建文件系统 90 fs, err := filesystem.NewFileSystem(job.User) 91 if err != nil { 92 job.SetErrorMsg(err.Error()) 93 return 94 } 95 96 util.Log().Debug("Starting compress file...") 97 job.TaskModel.SetProgress(CompressingProgress) 98 99 // 创建临时压缩文件 100 saveFolder := "compress" 101 zipFilePath := filepath.Join( 102 util.RelativePath(model.GetSettingByName("temp_path")), 103 saveFolder, 104 fmt.Sprintf("archive_%d.zip", time.Now().UnixNano()), 105 ) 106 zipFile, err := util.CreatNestedFile(zipFilePath) 107 if err != nil { 108 util.Log().Warning("%s", err) 109 job.SetErrorMsg(err.Error()) 110 return 111 } 112 113 defer zipFile.Close() 114 115 // 开始压缩 116 ctx := context.Background() 117 err = fs.Compress(ctx, zipFile, job.TaskProps.Dirs, job.TaskProps.Files, false) 118 if err != nil { 119 job.SetErrorMsg(err.Error()) 120 return 121 } 122 123 job.zipPath = zipFilePath 124 zipFile.Close() 125 util.Log().Debug("Compressed file saved to %q, start uploading it...", zipFilePath) 126 job.TaskModel.SetProgress(TransferringProgress) 127 128 // 上传文件 129 err = fs.UploadFromPath(ctx, zipFilePath, job.TaskProps.Dst, 0) 130 if err != nil { 131 job.SetErrorMsg(err.Error()) 132 return 133 } 134 135 job.removeZipFile() 136 } 137 138 // NewCompressTask 新建压缩任务 139 func NewCompressTask(user *model.User, dst string, dirs, files []uint) (Job, error) { 140 newTask := &CompressTask{ 141 User: user, 142 TaskProps: CompressProps{ 143 Dirs: dirs, 144 Files: files, 145 Dst: dst, 146 }, 147 } 148 149 record, err := Record(newTask) 150 if err != nil { 151 return nil, err 152 } 153 newTask.TaskModel = record 154 155 return newTask, nil 156 } 157 158 // NewCompressTaskFromModel 从数据库记录中恢复压缩任务 159 func NewCompressTaskFromModel(task *model.Task) (Job, error) { 160 user, err := model.GetActiveUserByID(task.UserID) 161 if err != nil { 162 return nil, err 163 } 164 newTask := &CompressTask{ 165 User: &user, 166 TaskModel: task, 167 } 168 169 err = json.Unmarshal([]byte(task.Props), &newTask.TaskProps) 170 if err != nil { 171 return nil, err 172 } 173 174 return newTask, nil 175 }