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

     1  package baidupcs
     2  
     3  import (
     4  	"errors"
     5  	"github.com/fzfile/BaiduPCS-Go/baidupcs/pcserror"
     6  	"github.com/fzfile/BaiduPCS-Go/pcsutil/converter"
     7  	"net/http"
     8  	"path"
     9  )
    10  
    11  const (
    12  	// MaxUploadBlockSize 最大上传的文件分片大小
    13  	MaxUploadBlockSize = 2 * converter.GB
    14  	// MinUploadBlockSize 最小的上传的文件分片大小
    15  	MinUploadBlockSize = 4 * converter.MB
    16  	// MaxRapidUploadSize 秒传文件支持的最大文件大小
    17  	MaxRapidUploadSize = 20 * converter.GB
    18  	// RecommendUploadBlockSize 推荐的上传的文件分片大小
    19  	RecommendUploadBlockSize = 1 * converter.GB
    20  	// SliceMD5Size 计算 slice-md5 所需的长度
    21  	SliceMD5Size = 256 * converter.KB
    22  	// EmptyContentMD5 空串的md5
    23  	EmptyContentMD5 = "d41d8cd98f00b204e9800998ecf8427e"
    24  )
    25  
    26  var (
    27  	// ErrUploadMD5NotFound 未找到md5
    28  	ErrUploadMD5NotFound = errors.New("unknown response data, md5 not found")
    29  	// ErrUploadSavePathFound 未找到保存路径
    30  	ErrUploadSavePathFound = errors.New("unknown response data, file saved path not found")
    31  	// ErrUploadSeqNotMatch 服务器返回的上传队列不匹配
    32  	ErrUploadSeqNotMatch = errors.New("服务器返回的上传队列不匹配")
    33  )
    34  
    35  type (
    36  	// UploadFunc 上传文件处理函数
    37  	UploadFunc func(uploadURL string, jar http.CookieJar) (resp *http.Response, err error)
    38  
    39  	// RapidUploadInfo 文件秒传信息
    40  	RapidUploadInfo struct {
    41  		Filename      string
    42  		ContentLength int64
    43  		ContentMD5    string
    44  		SliceMD5      string
    45  		ContentCrc32  string
    46  	}
    47  
    48  	uploadJSON struct {
    49  		*PathJSON
    50  		*pcserror.PCSErrInfo
    51  	}
    52  
    53  	uploadTmpFileJSON struct {
    54  		MD5 string `json:"md5"`
    55  		*pcserror.PCSErrInfo
    56  	}
    57  
    58  	uploadPrecreateJSON struct {
    59  		ReturnType int    `json:"return_type"` // 1上传, 2秒传
    60  		UploadID   string `json:"uploadid"`
    61  		BlockList  []int  `json:"block_list"`
    62  		*pcserror.PanErrorInfo
    63  		fdJSON `json:"info"`
    64  	}
    65  
    66  	// UploadSeq 分片上传顺序
    67  	UploadSeq struct {
    68  		Seq   int
    69  		Block string
    70  	}
    71  
    72  	// PrecreateInfo 预提交文件消息返回数据
    73  	PrecreateInfo struct {
    74  		IsRapidUpload bool
    75  		UploadID      string
    76  		UploadSeqList []*UploadSeq
    77  	}
    78  
    79  	uploadSuperfile2JSON struct {
    80  		MD5 string `json:"md5"`
    81  		*pcserror.PCSErrInfo
    82  	}
    83  )
    84  
    85  // RapidUpload 秒传文件
    86  func (pcs *BaiduPCS) RapidUpload(targetPath, contentMD5, sliceMD5, crc32 string, length int64) (pcsError pcserror.Error) {
    87  	dataReadCloser, pcsError := pcs.PrepareRapidUpload(targetPath, contentMD5, sliceMD5, crc32, length)
    88  	if pcsError != nil {
    89  		return
    90  	}
    91  
    92  	defer dataReadCloser.Close()
    93  
    94  	pcsError = pcserror.DecodePCSJSONError(OperationRapidUpload, dataReadCloser)
    95  	if pcsError != nil {
    96  		return
    97  	}
    98  
    99  	// 更新缓存
   100  	pcs.deleteCache([]string{path.Dir(targetPath)})
   101  	return nil
   102  }
   103  
   104  // RapidUploadNoCheckDir 秒传文件, 不进行目录检查, 会覆盖掉同名的目录!
   105  func (pcs *BaiduPCS) RapidUploadNoCheckDir(targetPath, contentMD5, sliceMD5, crc32 string, length int64) (pcsError pcserror.Error) {
   106  	dataReadCloser, pcsError := pcs.prepareRapidUpload(targetPath, contentMD5, sliceMD5, crc32, length)
   107  	if pcsError != nil {
   108  		return
   109  	}
   110  
   111  	defer dataReadCloser.Close()
   112  
   113  	pcsError = pcserror.DecodePCSJSONError(OperationRapidUpload, dataReadCloser)
   114  	if pcsError != nil {
   115  		return
   116  	}
   117  
   118  	return nil
   119  }
   120  
   121  // Upload 上传单个文件
   122  func (pcs *BaiduPCS) Upload(targetPath string, uploadFunc UploadFunc) (pcsError pcserror.Error) {
   123  	dataReadCloser, pcsError := pcs.PrepareUpload(targetPath, uploadFunc)
   124  	if pcsError != nil {
   125  		return pcsError
   126  	}
   127  
   128  	defer dataReadCloser.Close()
   129  
   130  	// 数据处理
   131  	jsonData := uploadJSON{
   132  		PCSErrInfo: pcserror.NewPCSErrorInfo(OperationUpload),
   133  	}
   134  
   135  	pcsError = pcserror.HandleJSONParse(OperationUpload, dataReadCloser, &jsonData)
   136  	if pcsError != nil {
   137  		return
   138  	}
   139  
   140  	if jsonData.Path == "" {
   141  		jsonData.PCSErrInfo.ErrType = pcserror.ErrTypeInternalError
   142  		jsonData.PCSErrInfo.Err = ErrUploadSavePathFound
   143  		return jsonData.PCSErrInfo
   144  	}
   145  
   146  	// 更新缓存
   147  	pcs.deleteCache([]string{path.Dir(targetPath)})
   148  	return nil
   149  }
   150  
   151  // UploadTmpFile 分片上传—文件分片及上传
   152  func (pcs *BaiduPCS) UploadTmpFile(uploadFunc UploadFunc) (md5 string, pcsError pcserror.Error) {
   153  	dataReadCloser, pcsError := pcs.PrepareUploadTmpFile(uploadFunc)
   154  	if pcsError != nil {
   155  		return "", pcsError
   156  	}
   157  
   158  	defer dataReadCloser.Close()
   159  
   160  	// 数据处理
   161  	jsonData := uploadTmpFileJSON{
   162  		PCSErrInfo: pcserror.NewPCSErrorInfo(OperationUploadTmpFile),
   163  	}
   164  
   165  	pcsError = pcserror.HandleJSONParse(OperationUploadTmpFile, dataReadCloser, &jsonData)
   166  	if pcsError != nil {
   167  		return
   168  	}
   169  
   170  	// 未找到md5
   171  	if jsonData.MD5 == "" {
   172  		jsonData.PCSErrInfo.ErrType = pcserror.ErrTypeInternalError
   173  		jsonData.PCSErrInfo.Err = ErrUploadMD5NotFound
   174  		return "", jsonData.PCSErrInfo
   175  	}
   176  
   177  	return jsonData.MD5, nil
   178  }
   179  
   180  // UploadCreateSuperFile 分片上传—合并分片文件
   181  func (pcs *BaiduPCS) UploadCreateSuperFile(checkDir bool, targetPath string, blockList ...string) (pcsError pcserror.Error) {
   182  	dataReadCloser, pcsError := pcs.PrepareUploadCreateSuperFile(checkDir, targetPath, blockList...)
   183  	if pcsError != nil {
   184  		return pcsError
   185  	}
   186  
   187  	defer dataReadCloser.Close()
   188  
   189  	errInfo := pcserror.DecodePCSJSONError(OperationUploadCreateSuperFile, dataReadCloser)
   190  	if errInfo != nil {
   191  		return errInfo
   192  	}
   193  
   194  	// 更新缓存
   195  	pcs.deleteCache([]string{path.Dir(targetPath)})
   196  	return nil
   197  }
   198  
   199  // UploadPrecreate 分片上传—Precreate,
   200  // 支持检验秒传
   201  func (pcs *BaiduPCS) UploadPrecreate(targetPath, contentMD5, sliceMD5, crc32 string, size int64, bolckList ...string) (precreateInfo *PrecreateInfo, pcsError pcserror.Error) {
   202  	dataReadCloser, pcsError := pcs.PrepareUploadPrecreate(targetPath, contentMD5, sliceMD5, crc32, size, bolckList...)
   203  	if pcsError != nil {
   204  		return
   205  	}
   206  
   207  	defer dataReadCloser.Close()
   208  
   209  	errInfo := pcserror.NewPanErrorInfo(OperationUploadPrecreate)
   210  	jsonData := uploadPrecreateJSON{
   211  		PanErrorInfo: errInfo,
   212  	}
   213  
   214  	pcsError = pcserror.HandleJSONParse(OperationUploadPrecreate, dataReadCloser, &jsonData)
   215  	if pcsError != nil {
   216  		return
   217  	}
   218  
   219  	switch jsonData.ReturnType {
   220  	case 1: // 上传
   221  		seqLen := len(jsonData.BlockList)
   222  		if seqLen != len(bolckList) {
   223  			errInfo.ErrType = pcserror.ErrTypeRemoteError
   224  			errInfo.Err = ErrUploadSeqNotMatch
   225  			return nil, errInfo
   226  		}
   227  
   228  		seqList := make([]*UploadSeq, 0, seqLen)
   229  		for k, seq := range jsonData.BlockList {
   230  			seqList = append(seqList, &UploadSeq{
   231  				Seq:   seq,
   232  				Block: bolckList[k],
   233  			})
   234  		}
   235  		return &PrecreateInfo{
   236  			UploadID:      jsonData.UploadID,
   237  			UploadSeqList: seqList,
   238  		}, nil
   239  
   240  	case 2: // 秒传
   241  		return &PrecreateInfo{
   242  			IsRapidUpload: true,
   243  		}, nil
   244  
   245  	default:
   246  		panic("unknown returntype")
   247  	}
   248  }
   249  
   250  // UploadSuperfile2 分片上传—Superfile2
   251  func (pcs *BaiduPCS) UploadSuperfile2(uploadid, targetPath string, partseq int, partOffset int64, uploadFunc UploadFunc) (md5sum string, pcsError pcserror.Error) {
   252  	dataReadCloser, pcsError := pcs.PrepareUploadSuperfile2(uploadid, targetPath, partseq, partOffset, uploadFunc)
   253  	if pcsError != nil {
   254  		return
   255  	}
   256  
   257  	defer dataReadCloser.Close()
   258  
   259  	jsonData := uploadSuperfile2JSON{
   260  		PCSErrInfo: pcserror.NewPCSErrorInfo(OperationUploadSuperfile2),
   261  	}
   262  
   263  	pcsError = pcserror.HandleJSONParse(OperationUploadSuperfile2, dataReadCloser, &jsonData)
   264  	if pcsError != nil {
   265  		return
   266  	}
   267  
   268  	return jsonData.MD5, nil
   269  }