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  }