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 }