github.com/fzfile/BaiduPCS-Go@v0.0.0-20200606205115-4408961cf336/baidupcs/cloud_dl.go (about)

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