github.com/qjfoidnh/BaiduPCS-Go@v0.0.0-20231011165705-caa18a3765f3/baidupcs/cloud_dl.go (about)

     1  package baidupcs
     2  
     3  import (
     4  	"errors"
     5  	"github.com/qjfoidnh/BaiduPCS-Go/baidupcs/pcserror"
     6  	"github.com/qjfoidnh/BaiduPCS-Go/pcstable"
     7  	"github.com/qjfoidnh/BaiduPCS-Go/pcsutil/converter"
     8  	"github.com/qjfoidnh/BaiduPCS-Go/pcsutil/pcstime"
     9  	"io"
    10  	"path"
    11  	"strconv"
    12  	"strings"
    13  )
    14  
    15  type (
    16  	// CloudDlFileInfo 离线下载的文件信息
    17  	CloudDlFileInfo struct {
    18  		FileName string `json:"file_name"`
    19  		FileSize int64  `json:"file_size"`
    20  	}
    21  
    22  	// CloudDlTaskInfo 离线下载的任务信息
    23  	CloudDlTaskInfo struct {
    24  		TaskID       int64
    25  		Status       int // 0下载成功, 1下载进行中, 2系统错误, 3资源不存在, 4下载超时, 5资源存在但下载失败, 6存储空间不足, 7任务取消
    26  		StatusText   string
    27  		FileSize     int64  // 文件大小
    28  		FinishedSize int64  // 文件大小
    29  		CreateTime   int64  // 创建时间
    30  		StartTime    int64  // 开始时间
    31  		FinishTime   int64  // 结束时间
    32  		SavePath     string // 保存的路径
    33  		SourceURL    string // 资源地址
    34  		TaskName     string // 任务名称, 一般为文件名
    35  		OdType       int
    36  		FileList     []*CloudDlFileInfo
    37  		Result       int // 0查询成功,结果有效,1要查询的task_id不存在
    38  	}
    39  
    40  	// CloudDlTaskList 离线下载的任务信息列表
    41  	CloudDlTaskList []*CloudDlTaskInfo
    42  
    43  	// cloudDlTaskInfo 用于解析远程返回的JSON
    44  	cloudDlTaskInfo struct {
    45  		Status       string `json:"status"`
    46  		TaskID       string `json:"task_id"`
    47  		FileSize     string `json:"file_size"`
    48  		FinishedSize string `json:"finished_size"`
    49  		CreateTime   string `json:"create_time"`
    50  		StartTime    string `json:"start_time"`
    51  		FinishTime   string `json:"finish_time"`
    52  		SavePath     string `json:"save_path"`
    53  		SourceURL    string `json:"source_url"`
    54  		TaskName     string `json:"task_name"`
    55  		OdType       string `json:"od_type"`
    56  		FileList     []*struct {
    57  			FileName string `json:"file_name"`
    58  			FileSize string `json:"file_size"`
    59  		} `json:"file_list"`
    60  		Result int `json:"result"`
    61  	}
    62  
    63  	taskIDInt64JSON struct {
    64  		TaskID int64 `json:"task_id"`
    65  	}
    66  
    67  	cloudDlAddTaskJSON struct {
    68  		*pcserror.PCSErrInfo
    69  		taskIDInt64JSON
    70  	}
    71  
    72  	cloudDlQueryTaskJSON struct {
    73  		TaskInfo map[string]*cloudDlTaskInfo `json:"task_info"`
    74  		*pcserror.PCSErrInfo
    75  	}
    76  
    77  	cloudDlListTaskJSON struct {
    78  		TaskInfo []*cloudDlTaskInfo `json:"task_info"`
    79  		*pcserror.PCSErrInfo
    80  	}
    81  
    82  	cloudDlClearJSON struct {
    83  		Total int `json:"total"`
    84  		*pcserror.PCSErrInfo
    85  	}
    86  )
    87  
    88  func (ci *cloudDlTaskInfo) convert() *CloudDlTaskInfo {
    89  	ci2 := &CloudDlTaskInfo{
    90  		Status:       converter.MustInt(ci.Status),
    91  		FileSize:     converter.MustInt64(ci.FileSize),
    92  		FinishedSize: converter.MustInt64(ci.FinishedSize),
    93  		CreateTime:   converter.MustInt64(ci.CreateTime),
    94  		StartTime:    converter.MustInt64(ci.StartTime),
    95  		FinishTime:   converter.MustInt64(ci.FinishTime),
    96  		SavePath:     ci.SavePath,
    97  		SourceURL:    ci.SourceURL,
    98  		TaskName:     ci.TaskName,
    99  		OdType:       converter.MustInt(ci.OdType),
   100  		Result:       ci.Result,
   101  	}
   102  
   103  	ci2.FileList = make([]*CloudDlFileInfo, 0, len(ci.FileList))
   104  	for _, v := range ci.FileList {
   105  		if v == nil {
   106  			continue
   107  		}
   108  
   109  		ci2.FileList = append(ci2.FileList, &CloudDlFileInfo{
   110  			FileName: v.FileName,
   111  			FileSize: converter.MustInt64(v.FileSize),
   112  		})
   113  	}
   114  
   115  	return ci2
   116  }
   117  
   118  // CloudDlAddTask 添加离线下载任务
   119  func (pcs *BaiduPCS) CloudDlAddTask(sourceURL, savePath string) (taskID int64, pcsError pcserror.Error) {
   120  	dataReadCloser, pcsError := pcs.PrepareCloudDlAddTask(sourceURL, savePath)
   121  	if pcsError != nil {
   122  		return
   123  	}
   124  
   125  	defer dataReadCloser.Close()
   126  
   127  	errInfo := pcserror.NewPCSErrorInfo(OperationCloudDlAddTask)
   128  	taskInfo := cloudDlAddTaskJSON{
   129  		PCSErrInfo: errInfo,
   130  	}
   131  
   132  	pcsError = pcserror.HandleJSONParse(OperationCloudDlAddTask, dataReadCloser, &taskInfo)
   133  	if pcsError != nil {
   134  		return
   135  	}
   136  
   137  	return taskInfo.TaskID, nil
   138  }
   139  
   140  func (pcs *BaiduPCS) cloudDlQueryTask(op string, taskIDs []int64) (cl CloudDlTaskList, pcsError pcserror.Error) {
   141  	errInfo := pcserror.NewPCSErrorInfo(op)
   142  	if len(taskIDs) == 0 {
   143  		errInfo.ErrType = pcserror.ErrTypeOthers
   144  		errInfo.Err = errors.New("no input any task_ids")
   145  		return nil, errInfo
   146  	}
   147  
   148  	// TODO: 支持100条以上的task_id查询
   149  	if len(taskIDs) > 100 {
   150  		taskIDs = taskIDs[:100]
   151  	}
   152  
   153  	taskStrIDs := make([]string, len(taskIDs))
   154  	for k := range taskStrIDs {
   155  		taskStrIDs[k] = strconv.FormatInt(taskIDs[k], 10)
   156  	}
   157  
   158  	dataReadCloser, pcsError := pcs.PrepareCloudDlQueryTask(strings.Join(taskStrIDs, ","))
   159  	if pcsError != nil {
   160  		return
   161  	}
   162  
   163  	defer dataReadCloser.Close()
   164  
   165  	taskInfo := cloudDlQueryTaskJSON{
   166  		PCSErrInfo: errInfo,
   167  	}
   168  
   169  	pcsError = pcserror.HandleJSONParse(OperationCloudDlQueryTask, dataReadCloser, &taskInfo)
   170  	if pcsError != nil {
   171  		return
   172  	}
   173  
   174  	var v2 *CloudDlTaskInfo
   175  	cl = make(CloudDlTaskList, 0, len(taskStrIDs))
   176  	for k := range taskStrIDs {
   177  		var err error
   178  		v := taskInfo.TaskInfo[taskStrIDs[k]]
   179  		if v == nil {
   180  			continue
   181  		}
   182  
   183  		v2 = v.convert()
   184  
   185  		v2.TaskID, err = strconv.ParseInt(taskStrIDs[k], 10, 64)
   186  		if err != nil {
   187  			continue
   188  		}
   189  
   190  		v2.ParseText()
   191  		cl = append(cl, v2)
   192  	}
   193  
   194  	return cl, nil
   195  }
   196  
   197  // CloudDlQueryTask 精确查询离线下载任务
   198  func (pcs *BaiduPCS) CloudDlQueryTask(taskIDs []int64) (cl CloudDlTaskList, pcsError pcserror.Error) {
   199  	return pcs.cloudDlQueryTask(OperationCloudDlQueryTask, taskIDs)
   200  }
   201  
   202  // CloudDlListTask 查询离线下载任务列表
   203  func (pcs *BaiduPCS) CloudDlListTask() (cl CloudDlTaskList, pcsError pcserror.Error) {
   204  	dataReadCloser, pcsError := pcs.PrepareCloudDlListTask()
   205  	if pcsError != nil {
   206  		return
   207  	}
   208  
   209  	defer dataReadCloser.Close()
   210  
   211  	errInfo := pcserror.NewPCSErrorInfo(OperationCloudDlListTask)
   212  	taskInfo := cloudDlListTaskJSON{
   213  		PCSErrInfo: errInfo,
   214  	}
   215  
   216  	pcsError = pcserror.HandleJSONParse(OperationCloudDlListTask, dataReadCloser, &taskInfo)
   217  	if pcsError != nil {
   218  		return
   219  	}
   220  
   221  	// 没有任务
   222  	if len(taskInfo.TaskInfo) <= 0 {
   223  		return CloudDlTaskList{}, nil
   224  	}
   225  	cl = make([]*CloudDlTaskInfo, 0, len(taskInfo.TaskInfo))
   226  	var v2 *CloudDlTaskInfo
   227  	for _, v := range taskInfo.TaskInfo {
   228  		var err error
   229  		if v == nil {
   230  			continue
   231  		}
   232  		v2 = v.convert()
   233  		v2.TaskID, err = strconv.ParseInt(v.TaskID, 10, 64)
   234  		if err != nil {
   235  			continue
   236  		}
   237  		v2.ParseText()
   238  		cl = append(cl, v2)
   239  	}
   240  
   241  	return cl, nil
   242  }
   243  
   244  func (pcs *BaiduPCS) cloudDlManipTask(op string, taskID int64) (pcsError pcserror.Error) {
   245  	var dataReadCloser io.ReadCloser
   246  
   247  	switch op {
   248  	case OperationCloudDlCancelTask:
   249  		dataReadCloser, pcsError = pcs.PrepareCloudDlCancelTask(taskID)
   250  	case OperationCloudDlDeleteTask:
   251  		dataReadCloser, pcsError = pcs.PrepareCloudDlDeleteTask(taskID)
   252  	default:
   253  		panic("unknown op, " + op)
   254  	}
   255  	if pcsError != nil {
   256  		return
   257  	}
   258  
   259  	defer dataReadCloser.Close()
   260  
   261  	errInfo := pcserror.DecodePCSJSONError(op, dataReadCloser)
   262  	return errInfo
   263  }
   264  
   265  // CloudDlCancelTask 取消离线下载任务
   266  func (pcs *BaiduPCS) CloudDlCancelTask(taskID int64) (pcsError pcserror.Error) {
   267  	return pcs.cloudDlManipTask(OperationCloudDlCancelTask, taskID)
   268  }
   269  
   270  // CloudDlDeleteTask 删除离线下载任务
   271  func (pcs *BaiduPCS) CloudDlDeleteTask(taskID int64) (pcsError pcserror.Error) {
   272  	return pcs.cloudDlManipTask(OperationCloudDlDeleteTask, taskID)
   273  }
   274  
   275  // CloudDlClearTask 清空离线下载任务记录
   276  func (pcs *BaiduPCS) CloudDlClearTask() (total int, pcsError pcserror.Error) {
   277  	dataReadCloser, pcsError := pcs.PrepareCloudDlClearTask()
   278  	if pcsError != nil {
   279  		return
   280  	}
   281  
   282  	defer dataReadCloser.Close()
   283  
   284  	errInfo := pcserror.NewPCSErrorInfo(OperationCloudDlClearTask)
   285  	clearInfo := cloudDlClearJSON{
   286  		PCSErrInfo: errInfo,
   287  	}
   288  
   289  	pcsError = pcserror.HandleJSONParse(OperationCloudDlClearTask, dataReadCloser, &clearInfo)
   290  	if pcsError != nil {
   291  		return
   292  	}
   293  
   294  	return clearInfo.Total, nil
   295  }
   296  
   297  // ParseText 解析状态码
   298  func (ci *CloudDlTaskInfo) ParseText() {
   299  	switch ci.Status {
   300  	case 0:
   301  		ci.StatusText = "下载成功"
   302  	case 1:
   303  		ci.StatusText = "下载进行中"
   304  	case 2:
   305  		ci.StatusText = "系统错误"
   306  	case 3:
   307  		ci.StatusText = "资源不存在"
   308  	case 4:
   309  		ci.StatusText = "下载超时"
   310  	case 5:
   311  		ci.StatusText = "资源存在但下载失败"
   312  	case 6:
   313  		ci.StatusText = "存储空间不足"
   314  	case 7:
   315  		ci.StatusText = "任务取消"
   316  	default:
   317  		ci.StatusText = "未知状态码: " + strconv.Itoa(ci.Status)
   318  	}
   319  }
   320  
   321  func (cl CloudDlTaskList) String() string {
   322  	builder := &strings.Builder{}
   323  	tb := pcstable.NewTable(builder)
   324  	tb.SetHeader([]string{"#", "任务ID", "任务名称", "文件大小", "创建日期", "保存路径", "资源地址", "状态"})
   325  	for k, v := range cl {
   326  		tb.Append([]string{strconv.Itoa(k), strconv.FormatInt(v.TaskID, 10), v.TaskName, converter.ConvertFileSize(v.FileSize), pcstime.FormatTime(v.CreateTime), path.Clean(v.SavePath), v.SourceURL, v.StatusText})
   327  	}
   328  	tb.Render()
   329  	return builder.String()
   330  }