github.com/qjfoidnh/BaiduPCS-Go@v0.0.0-20231011165705-caa18a3765f3/baidupcs/prepare.go (about) 1 package baidupcs 2 3 import ( 4 "bytes" 5 "io" 6 "net/http" 7 "net/url" 8 "path" 9 "strconv" 10 "strings" 11 "unsafe" 12 13 jsoniter "github.com/json-iterator/go" 14 "github.com/qjfoidnh/BaiduPCS-Go/baidupcs/netdisksign" 15 "github.com/qjfoidnh/BaiduPCS-Go/baidupcs/pcserror" 16 "github.com/qjfoidnh/BaiduPCS-Go/pcsutil/converter" 17 "github.com/qjfoidnh/BaiduPCS-Go/requester/multipartreader" 18 "github.com/qjfoidnh/baidu-tools/tieba" 19 ) 20 21 type ( 22 reqType int 23 ) 24 25 const ( 26 reqTypePCS = iota 27 reqTypePan 28 ) 29 30 func handleRespClose(resp *http.Response) error { 31 if resp != nil { 32 return resp.Body.Close() 33 } 34 return nil 35 } 36 37 func handleRespStatusError(opreation string, resp *http.Response) pcserror.Error { 38 //errInfo := pcserror.NewPCSErrorInfo(opreation) 39 // http 响应错误处理 40 switch resp.StatusCode / 100 { 41 case 4, 5: 42 errInfo := pcserror.DecodePCSJSONError(opreation, resp.Body) 43 resp.Body.Close() 44 errInfo.SetRemoteError() 45 //errInfo.SetNetError(fmt.Errorf("http 响应错误, %s", resp.Status)) 46 return errInfo 47 } 48 49 return nil 50 } 51 52 func (pcs *BaiduPCS) sendReqReturnResp(rt reqType, op, method, urlStr string, post interface{}, header map[string]string) (resp *http.Response, pcsError pcserror.Error) { 53 if header == nil { 54 header = map[string]string{} 55 } 56 57 var ( 58 _, uaok = header["User-Agent"] 59 ) 60 61 if !uaok { 62 switch rt { 63 case reqTypePCS: 64 header["User-Agent"] = pcs.pcsUA 65 case reqTypePan: 66 header["User-Agent"] = pcs.panUA 67 } 68 } 69 70 resp, err := pcs.client.Req(method, urlStr, post, header) 71 if err != nil { 72 handleRespClose(resp) 73 switch rt { 74 case reqTypePCS: 75 return nil, &pcserror.PCSErrInfo{ 76 Operation: op, 77 ErrType: pcserror.ErrTypeNetError, 78 Err: err, 79 } 80 case reqTypePan: 81 return nil, &pcserror.PanErrorInfo{ 82 Operation: op, 83 ErrType: pcserror.ErrTypeNetError, 84 Err: err, 85 } 86 } 87 panic("unreachable") 88 } 89 return resp, nil 90 } 91 92 func (pcs *BaiduPCS) sendReqReturnReadCloser(rt reqType, op, method, urlStr string, post interface{}, header map[string]string) (readCloser io.ReadCloser, pcsError pcserror.Error) { 93 resp, pcsError := pcs.sendReqReturnResp(rt, op, method, urlStr, post, header) 94 if pcsError != nil { 95 return 96 } 97 return resp.Body, nil 98 } 99 100 // PrepareUK 获取用户 UK, 只返回服务器响应数据和错误信息 101 func (pcs *BaiduPCS) PrepareUK() (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 102 pcs.lazyInit() 103 104 query := url.Values{} 105 query.Set("need_selfinfo", "1") 106 107 panURL := &url.URL{ 108 Scheme: "https", 109 Host: PanBaiduCom, 110 Path: "api/user/getinfo", 111 RawQuery: query.Encode(), 112 } 113 114 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationGetUK, http.MethodGet, panURL.String(), nil, nil) 115 return 116 } 117 118 // PrepareQuotaInfo 获取当前用户空间配额信息, 只返回服务器响应数据和错误信息 119 func (pcs *BaiduPCS) PrepareQuotaInfo() (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 120 pcs.lazyInit() 121 pcsURL := pcs.generatePCSURL("quota", "info") 122 baiduPCSVerbose.Infof("%s URL: %s\n", OperationQuotaInfo, pcsURL) 123 124 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationQuotaInfo, http.MethodGet, pcsURL.String(), nil, nil) 125 return 126 } 127 128 // PrepareFilesDirectoriesBatchMeta 获取多个文件/目录的元信息, 只返回服务器响应数据和错误信息 129 func (pcs *BaiduPCS) PrepareFilesDirectoriesBatchMeta(paths ...string) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 130 pcs.lazyInit() 131 sendData, err := (&PathsListJSON{}).JSON(paths...) 132 if err != nil { 133 panic(OperationFilesDirectoriesMeta + ", json 数据构造失败, " + err.Error()) 134 } 135 136 pcsURL := pcs.generatePCSURL("file", "meta") 137 baiduPCSVerbose.Infof("%s URL: %s\n", OperationFilesDirectoriesMeta, pcsURL) 138 139 // 表单上传 140 mr := multipartreader.NewMultipartReader() 141 mr.AddFormFeild("param", bytes.NewReader(sendData)) 142 mr.CloseMultipart() 143 144 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationFilesDirectoriesMeta, http.MethodPost, pcsURL.String(), mr, nil) 145 return 146 } 147 148 // PrepareFilesDirectoriesList 获取目录下的文件和目录列表, 只返回服务器响应数据和错误信息 149 func (pcs *BaiduPCS) PrepareFilesDirectoriesList(path string, options *OrderOptions) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 150 pcs.lazyInit() 151 if options == nil { 152 options = DefaultOrderOptions 153 } 154 if path == "" { 155 path = PathSeparator 156 } 157 158 pcsURL := pcs.generatePCSURL("file", "list", map[string]string{ 159 "path": path, 160 "by": *(*string)(unsafe.Pointer(&options.By)), 161 "order": *(*string)(unsafe.Pointer(&options.Order)), 162 "limit": "0-2147483647", 163 }) 164 baiduPCSVerbose.Infof("%s URL: %s\n", OperationFilesDirectoriesList, pcsURL) 165 166 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationFilesDirectoriesList, http.MethodGet, pcsURL.String(), nil, nil) 167 return 168 } 169 170 func (pcs *BaiduPCS) PrepareFilesDirectoriesDiff(cursor string) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 171 pcs.lazyInit() 172 //bdstoken, pcsError := pcs.BDSToken() 173 //if pcsError != nil { 174 // return 175 //} 176 if cursor == "" { 177 cursor = "null" 178 } 179 ns := netdisksign.NewLocateDownloadSign(pcs.uid, pcs.GetBDUSS()) 180 pcsURL := pcs.generatePanURL("batch/filediff", map[string]string{ 181 "cursor": cursor, 182 //"bdstoken": bdstoken, 183 "clienttype": "1", 184 }) 185 paramsURL := ns.URLParam() 186 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationGetCursorDiff, http.MethodGet, pcsURL.String() + "&"+ paramsURL, nil, nil) 187 return 188 } 189 190 func (pcs *BaiduPCS) PrepareBDStoken() (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 191 pcs.lazyInit() 192 pcsURL := pcs.generatePanURL("gettemplatevariable", map[string]string{ 193 "clienttype": "0", 194 "app_id": string(pcs.appID), 195 "fields": `["bdstoken"]`, 196 }) 197 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationGetBDSToken, http.MethodGet, pcsURL.String(), nil, nil) 198 return 199 } 200 201 // PrepareSearch 按文件名搜索文件, 只返回服务器响应数据和错误信息 202 func (pcs *BaiduPCS) PrepareSearch(targetPath, keyword string, recursive bool) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 203 pcs.lazyInit() 204 var re string 205 if recursive { 206 re = "1" 207 } else { 208 re = "0" 209 } 210 pcsURL := pcs.generatePCSURL("file", "search", map[string]string{ 211 "path": targetPath, 212 "wd": keyword, 213 "re": re, 214 }) 215 baiduPCSVerbose.Infof("%s URL: %s\n", OperationSearch, pcsURL) 216 217 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationSearch, http.MethodGet, pcsURL.String(), nil, nil) 218 return 219 } 220 221 // PrepareRemove 批量删除文件/目录, 只返回服务器响应数据和错误信息 222 func (pcs *BaiduPCS) PrepareRemove(paths ...string) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 223 pcs.lazyInit() 224 sendData, err := (&PathsListJSON{}).JSON(paths...) 225 if err != nil { 226 panic(OperationMove + ", json 数据构造失败, " + err.Error()) 227 } 228 229 pcsURL := pcs.generatePCSURL("file", "delete") 230 baiduPCSVerbose.Infof("%s URL: %s\n", OperationRemove, pcsURL) 231 232 // 表单上传 233 mr := multipartreader.NewMultipartReader() 234 mr.AddFormFeild("param", bytes.NewReader(sendData)) 235 mr.CloseMultipart() 236 237 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationRemove, http.MethodPost, pcsURL.String(), mr, nil) 238 return 239 } 240 241 // PrepareMkdir 创建目录, 只返回服务器响应数据和错误信息 242 func (pcs *BaiduPCS) PrepareMkdir(pcspath string) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 243 pcs.lazyInit() 244 pcsURL := pcs.generatePCSURL("file", "mkdir", map[string]string{ 245 "path": pcspath, 246 }) 247 baiduPCSVerbose.Infof("%s URL: %s", OperationMkdir, pcsURL) 248 249 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationMkdir, http.MethodPost, pcsURL.String(), nil, nil) 250 return 251 } 252 253 func (pcs *BaiduPCS) prepareCpMvOp(op string, cpmvJSON ...*CpMvJSON) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 254 pcs.lazyInit() 255 var method string 256 switch op { 257 case OperationCopy: 258 method = "copy" 259 case OperationMove, OperationRename: 260 method = "move" 261 default: 262 panic("Unknown opreation: " + op) 263 } 264 265 sendData, err := (&CpMvListJSON{ 266 List: cpmvJSON, 267 }).JSON() 268 if err != nil { 269 //json 数据生成失败 270 panic(err) 271 } 272 273 pcsURL := pcs.generatePCSURL("file", method) 274 baiduPCSVerbose.Infof("%s URL: %s\n", op, pcsURL) 275 276 // 表单上传 277 mr := multipartreader.NewMultipartReader() 278 mr.AddFormFeild("param", bytes.NewReader(sendData)) 279 mr.CloseMultipart() 280 281 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, op, http.MethodPost, pcsURL.String(), mr, nil) 282 return 283 } 284 285 // PrepareRename 重命名文件/目录, 只返回服务器响应数据和错误信息 286 func (pcs *BaiduPCS) PrepareRename(from, to string) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 287 return pcs.prepareCpMvOp(OperationRename, &CpMvJSON{ 288 From: from, 289 To: to, 290 }) 291 } 292 293 // PrepareCopy 批量拷贝文件/目录, 只返回服务器响应数据和错误信息 294 func (pcs *BaiduPCS) PrepareCopy(cpmvJSON ...*CpMvJSON) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 295 return pcs.prepareCpMvOp(OperationCopy, cpmvJSON...) 296 } 297 298 // PrepareMove 批量移动文件/目录, 只返回服务器响应数据和错误信息 299 func (pcs *BaiduPCS) PrepareMove(cpmvJSON ...*CpMvJSON) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 300 return pcs.prepareCpMvOp(OperationMove, cpmvJSON...) 301 } 302 303 // prepareRapidUpload 秒传文件, 不进行文件夹检查 304 func (pcs *BaiduPCS) prepareRapidUpload(targetPath, contentMD5, sliceMD5, crc32 string, length int64) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 305 //bdstoken, pcsError := pcs.BDSToken() 306 //if pcsError != nil { 307 // return 308 //} 309 pcsURL := pcs.generatePCSURL2("xpan/file", "create", map[string]string{ 310 "access_token": pcs.accessToken, 311 //"bdstoken": bdstoken, 312 }) 313 baiduPCSVerbose.Infof("%s URL: %s\n", OperationRapidUpload, pcsURL) 314 post := map[string]string{ 315 "block_list": mergeStringList(contentMD5), 316 "path": targetPath, 317 "size": strconv.FormatInt(length, 10), 318 "isdir": "0", 319 "rtype": "3", 320 } 321 baiduPCSVerbose.Infof("%s URL: %s, Post: %v\n", OperationRapidUpload, pcsURL, post) 322 323 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePan, OperationRapidUpload, http.MethodPost, pcsURL.String(), post, map[string]string{ 324 "Content-Type": "application/x-www-form-urlencoded", 325 }) 326 return 327 } 328 329 // prepareRapidUploadV2 秒传文件接口2, 不进行文件夹检查 330 func (pcs *BaiduPCS) prepareRapidUploadV2(targetPath, contentMD5, sliceMD5, dataContent, crc32 string, offset, length, totalSize, dataTime int64) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 331 pcsURL := pcs.generatePanURL("precreate", nil) 332 post := map[string]string{ 333 "path": targetPath, 334 "target_path": path.Dir(targetPath) + "/", 335 "size": strconv.FormatInt(totalSize, 10), 336 "data_offset": strconv.FormatInt(offset, 10), 337 "isdir": "0", 338 "local_mtime": strconv.FormatInt(dataTime, 10), 339 "local_ctime": strconv.FormatInt(dataTime, 10), 340 "rtype": "2", 341 "checkexist": "0", 342 "autoinit": "1", 343 "content-md5": contentMD5, 344 "slice-md5": sliceMD5, 345 "data_time": strconv.FormatInt(dataTime, 10), 346 "data_length": strconv.FormatInt(length, 10), 347 "data_content": dataContent, 348 "block_list": mergeStringList(contentMD5), 349 "mode": "1", 350 } 351 baiduPCSVerbose.Infof("%s URL: %s, Post: %v\n", OperationRapidUpload, pcsURL, post) 352 353 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePan, OperationRapidUpload, http.MethodPost, pcsURL.String(), post, map[string]string{ 354 "Content-Type": "application/x-www-form-urlencoded", 355 "Accept": "*/*", 356 "Connection": "keep-alive", 357 }) 358 return 359 } 360 361 // PrepareRapidUpload 秒传文件旧接口, 只返回服务器响应数据和错误信息 362 func (pcs *BaiduPCS) PrepareRapidUpload(targetPath, contentMD5, sliceMD5, crc32 string, length int64) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 363 pcs.lazyInit() 364 pcsError = pcs.CheckIsdir(OperationRapidUpload, targetPath, "", length) 365 if pcsError != nil { 366 return nil, pcsError 367 } 368 369 return pcs.prepareRapidUpload(targetPath, contentMD5, sliceMD5, crc32, length) 370 } 371 372 // PrepareRapidUploadV2 秒传文件新接口, 只返回服务器响应数据和错误信息 373 func (pcs *BaiduPCS) PrepareRapidUploadV2(targetPath, contentMD5, sliceMD5, dataContent, crc32 string, offset, length, totalSize, dataTime int64) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 374 pcs.lazyInit() 375 pcsError = pcs.CheckIsdir(OperationRapidUpload, targetPath, "", totalSize) 376 if pcsError != nil { 377 return nil, pcsError 378 } 379 return pcs.prepareRapidUploadV2(targetPath, contentMD5, sliceMD5, dataContent, crc32, offset, length, totalSize, dataTime) 380 } 381 382 // PrepareLocateDownload 获取下载链接, 只返回服务器响应数据和错误信息 383 func (pcs *BaiduPCS) PrepareLocateDownload(pcspath string) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 384 pcs.lazyInit() 385 bduss := pcs.GetBDUSS() 386 // 检测uid 387 if pcs.uid == 0 { 388 t, err := tieba.NewUserInfoByBDUSS(bduss) 389 if err != nil { 390 return nil, &pcserror.PCSErrInfo{ 391 Operation: OperationLocateDownload, 392 ErrType: pcserror.ErrTypeNetError, 393 Err: err, 394 } 395 } 396 pcs.uid = t.Baidu.UID 397 } 398 399 ns := netdisksign.NewLocateDownloadSign(pcs.uid, bduss) 400 pcsURL := &url.URL{ 401 Scheme: GetHTTPScheme(pcs.isHTTPS), 402 Host: pcs.URL().Host, 403 Path: "/rest/2.0/pcs/file", 404 RawQuery: (url.Values{ 405 "check_blue": []string{"1"}, 406 "es": []string{"1"}, 407 "esl": []string{"1"}, 408 "app_id": []string{PanAppID}, 409 "method": []string{"locatedownload"}, 410 "path": []string{pcspath}, 411 "ver": []string{"4.0"}, 412 "clienttype": []string{"17"}, 413 "channel": []string{"0"}, 414 "apn_id": []string{"1_0"}, 415 "freeisp": []string{"0"}, 416 "queryfree": []string{"0"}, 417 "use": []string{"0"}, 418 }).Encode() + "&" + ns.URLParam(), 419 } 420 baiduPCSVerbose.Infof("%s URL: %s\n", OperationLocateDownload, pcsURL) 421 422 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationLocateDownload, http.MethodGet, pcsURL.String(), nil, pcs.getPanUAHeader()) 423 return 424 } 425 426 // PrepareLocatePanAPIDownload 从百度网盘首页获取下载链接, 只返回服务器响应数据和错误信息 427 func (pcs *BaiduPCS) PrepareLocatePanAPIDownload(fidList ...int64) (dataReadCloser io.ReadCloser, panError pcserror.Error) { 428 pcs.lazyInit() 429 // 初始化 430 var ( 431 sign, err = pcs.ph.CacheSignature() 432 ) 433 if err != nil { 434 return nil, &pcserror.PanErrorInfo{ 435 Operation: OperationLocatePanAPIDownload, 436 ErrType: pcserror.ErrTypeOthers, 437 Err: err, 438 } 439 } 440 441 panURL := pcs.generatePanURL("download", nil) 442 baiduPCSVerbose.Infof("%s URL: %s\n", OperationLocatePanAPIDownload, panURL) 443 444 dataReadCloser, panError = pcs.sendReqReturnReadCloser(reqTypePan, OperationLocatePanAPIDownload, http.MethodPost, panURL.String(), map[string]string{ 445 "sign": sign.Sign(), 446 "timestamp": sign.Timestamp(), 447 "fidlist": mergeInt64List(fidList...), 448 }, map[string]string{ 449 "Content-Type": "application/x-www-form-urlencoded", 450 }) 451 return 452 } 453 454 // PrepareUpload 上传单个文件, 只返回服务器响应数据和错误信息(分片上传中的预上传部分) 455 func (pcs *BaiduPCS) PrepareUpload(policy string, targetPath string, uploadFunc UploadFunc) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 456 pcs.lazyInit() 457 458 pcsURL := pcs.generatePCSURL("file", "upload", map[string]string{ 459 "path": targetPath, 460 "ondup": strings.Replace(policy, "rsync", "overwrite", -1), 461 }) 462 baiduPCSVerbose.Infof("%s URL: %s\n", OperationUpload, pcsURL) 463 464 resp, err := uploadFunc(pcsURL.String(), pcs.client.Jar) 465 if err != nil { 466 handleRespClose(resp) 467 return nil, &pcserror.PCSErrInfo{ 468 Operation: OperationUpload, 469 ErrType: pcserror.ErrTypeNetError, 470 Err: err, 471 } 472 } 473 474 pcsError = handleRespStatusError(OperationUpload, resp) 475 if pcsError != nil { 476 return 477 } 478 479 return resp.Body, nil 480 } 481 482 // PrepareUploadTmpFile 分片上传—文件分片及上传, 只返回服务器响应数据和错误信息 483 func (pcs *BaiduPCS) PrepareUploadTmpFile(uploadFunc UploadFunc) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 484 pcs.lazyInit() 485 pcsURL := pcs.generatePCSURL("file", "upload", map[string]string{ 486 "type": "tmpfile", 487 }) 488 baiduPCSVerbose.Infof("%s URL: %s\n", OperationUploadTmpFile, pcsURL) 489 490 resp, err := uploadFunc(pcsURL.String(), pcs.client.Jar) 491 if err != nil { 492 handleRespClose(resp) 493 return nil, &pcserror.PCSErrInfo{ 494 Operation: OperationUploadTmpFile, 495 ErrType: pcserror.ErrTypeNetError, 496 Err: err, 497 } 498 } 499 500 pcsError = handleRespStatusError(OperationUploadTmpFile, resp) 501 if pcsError != nil { 502 return 503 } 504 505 return resp.Body, nil 506 } 507 508 // PrepareUploadCreateSuperFile 分片上传—合并分片文件, 只返回服务器响应数据和错误信息 509 func (pcs *BaiduPCS) PrepareUploadCreateSuperFile(policy string, checkDir bool, targetPath string, blockList ...string) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 510 pcs.lazyInit() 511 512 if checkDir { 513 // 检查是否为目录 514 pcsError = pcs.CheckIsdir(OperationUploadCreateSuperFile, targetPath, "", 0) 515 if pcsError != nil { 516 return nil, pcsError 517 } 518 } 519 520 bl := BlockListJSON{ 521 BlockList: blockList, 522 } 523 524 sendData, err := jsoniter.Marshal(&bl) 525 if err != nil { 526 panic(err) 527 } 528 529 pcsURL := pcs.generatePCSURL("file", "createsuperfile", map[string]string{ 530 "path": targetPath, 531 "ondup": strings.Replace(policy, "rsync", "overwrite", -1), 532 }) 533 baiduPCSVerbose.Infof("%s URL: %s\n", OperationUploadCreateSuperFile, pcsURL) 534 535 // 表单上传 536 mr := multipartreader.NewMultipartReader() 537 mr.AddFormFeild("param", bytes.NewReader(sendData)) 538 mr.CloseMultipart() 539 540 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationUploadCreateSuperFile, http.MethodPost, pcsURL.String(), mr, nil) 541 return 542 } 543 544 // PrepareUploadPrecreate 分片上传—Precreate, 只返回服务器响应数据和错误信息 545 func (pcs *BaiduPCS) PrepareUploadPrecreate(targetPath, contentMD5, sliceMD5, crc32 string, size int64, bolckList ...string) (dataReadCloser io.ReadCloser, panError pcserror.Error) { 546 pcs.lazyInit() 547 panURL := &url.URL{ 548 Scheme: "https", 549 Host: PanBaiduCom, 550 Path: "api/precreate", 551 } 552 baiduPCSVerbose.Infof("%s URL: %s\n", OperationUploadPrecreate, panURL) 553 554 dataReadCloser, panError = pcs.sendReqReturnReadCloser(reqTypePan, OperationUploadPrecreate, http.MethodPost, panURL.String(), map[string]string{ 555 "path": targetPath, 556 "size": strconv.FormatInt(size, 10), 557 "isdir": "0", 558 "block_list": mergeStringList(bolckList...), 559 "autoinit": "1", 560 "content-md5": contentMD5, 561 "slice-md5": sliceMD5, 562 "contentCrc32": crc32, 563 "rtype": "2", 564 }, map[string]string{ 565 "Content-Type": "application/x-www-form-urlencoded", 566 }) 567 return 568 } 569 570 // PrepareUploadSuperfile2 另一个上传接口 571 func (pcs *BaiduPCS) PrepareUploadSuperfile2(uploadid, targetPath string, partseq int, partOffset int64, uploadFunc UploadFunc) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 572 pcs.lazyInit() 573 pcsURL := pcs.generatePCSURL("superfile2", "upload", map[string]string{ 574 "type": "tmpfile", 575 "path": targetPath, 576 "partseq": strconv.Itoa(partseq), 577 "partoffset": strconv.FormatInt(partOffset, 10), 578 "uploadid": uploadid, 579 "vip": "1", 580 }) 581 baiduPCSVerbose.Infof("%s URL: %s\n", OperationUploadSuperfile2, pcsURL) 582 583 resp, err := uploadFunc(pcsURL.String(), pcs.client.Jar) 584 if err != nil { 585 handleRespClose(resp) 586 return nil, &pcserror.PCSErrInfo{ 587 Operation: OperationUploadSuperfile2, 588 ErrType: pcserror.ErrTypeNetError, 589 Err: err, 590 } 591 } 592 593 pcsError = handleRespStatusError(OperationUpload, resp) 594 if pcsError != nil { 595 return 596 } 597 return resp.Body, nil 598 } 599 600 // PrepareCloudDlAddTask 添加离线下载任务, 只返回服务器响应数据和错误信息 601 func (pcs *BaiduPCS) PrepareCloudDlAddTask(sourceURL, savePath string) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 602 pcs.lazyInit() 603 pcsURL2 := pcs.generatePCSURL2("services/cloud_dl", "add_task", map[string]string{ 604 "app_id": PanAppID, 605 "task_from": "0", 606 "selected_idx": "1", 607 "save_path": savePath, 608 "source_url": sourceURL, 609 }) 610 baiduPCSVerbose.Infof("%s URL: %s\n", OperationCloudDlAddTask, pcsURL2) 611 612 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationCloudDlAddTask, http.MethodPost, pcsURL2.String(), nil, nil) 613 return 614 } 615 616 // PrepareCloudDlQueryTask 精确查询离线下载任务, 只返回服务器响应数据和错误信息, 617 // taskids 例子: 12123,234234,2344, 用逗号隔开多个 task_id 618 func (pcs *BaiduPCS) PrepareCloudDlQueryTask(taskIDs string) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 619 pcs.lazyInit() 620 pcsURL2 := pcs.generatePCSURL2("services/cloud_dl", "query_task", map[string]string{ 621 "app_id": PanAppID, 622 "op_type": "1", 623 "task_ids": taskIDs, 624 }) 625 baiduPCSVerbose.Infof("%s URL: %s\n", OperationCloudDlQueryTask, pcsURL2) 626 627 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationCloudDlQueryTask, http.MethodGet, pcsURL2.String(), nil, nil) 628 return 629 } 630 631 // PrepareCloudDlListTask 查询离线下载任务列表, 只返回服务器响应数据和错误信息 632 func (pcs *BaiduPCS) PrepareCloudDlListTask() (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 633 pcs.lazyInit() 634 pcsURL2 := pcs.generatePCSURL2("services/cloud_dl", "list_task", map[string]string{ 635 "need_task_info": "1", 636 "status": "255", 637 "start": "0", 638 "limit": "1000", 639 "app_id": PanAppID, 640 }) 641 baiduPCSVerbose.Infof("%s URL: %s\n", OperationCloudDlListTask, pcsURL2) 642 643 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationCloudDlListTask, http.MethodPost, pcsURL2.String(), nil, nil) 644 return 645 } 646 647 func (pcs *BaiduPCS) prepareCloudDlCDTask(opreation, method string, taskID int64) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 648 pcs.lazyInit() 649 pcsURL2 := pcs.generatePCSURL2("services/cloud_dl", method, map[string]string{ 650 "app_id": PanAppID, 651 "task_id": strconv.FormatInt(taskID, 10), 652 }) 653 baiduPCSVerbose.Infof("%s URL: %s\n", opreation, pcsURL2) 654 655 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, opreation, http.MethodPost, pcsURL2.String(), nil, nil) 656 return 657 } 658 659 // PrepareCloudDlCancelTask 取消离线下载任务, 只返回服务器响应数据和错误信息 660 func (pcs *BaiduPCS) PrepareCloudDlCancelTask(taskID int64) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 661 return pcs.prepareCloudDlCDTask(OperationCloudDlCancelTask, "cancel_task", taskID) 662 } 663 664 // PrepareCloudDlDeleteTask 取消离线下载任务, 只返回服务器响应数据和错误信息 665 func (pcs *BaiduPCS) PrepareCloudDlDeleteTask(taskID int64) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 666 return pcs.prepareCloudDlCDTask(OperationCloudDlDeleteTask, "delete_task", taskID) 667 } 668 669 // PrepareCloudDlClearTask 清空离线下载任务记录, 只返回服务器响应数据和错误信息 670 func (pcs *BaiduPCS) PrepareCloudDlClearTask() (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 671 pcs.lazyInit() 672 pcsURL2 := pcs.generatePCSURL2("services/cloud_dl", "clear_task") 673 baiduPCSVerbose.Infof("%s URL: %s\n", OperationCloudDlClearTask, pcsURL2) 674 675 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationCloudDlClearTask, http.MethodPost, pcsURL2.String(), nil, nil) 676 return 677 } 678 679 // PrepareSharePSet 私密分享文件, 只返回服务器响应数据和错误信息 680 func (pcs *BaiduPCS) PrepareSharePSet(paths []string, pwd string, period int) (dataReadCloser io.ReadCloser, panError pcserror.Error) { 681 pcs.lazyInit() 682 panURL := &url.URL{ 683 Scheme: "https", 684 Host: PanBaiduCom, 685 Path: "share/pset", 686 } 687 baiduPCSVerbose.Infof("%s URL: %s\n", OperationShareSet, panURL) 688 689 dataReadCloser, panError = pcs.sendReqReturnReadCloser(reqTypePan, OperationShareSet, http.MethodPost, panURL.String(), map[string]string{ 690 "path_list": mergeStringList(paths...), 691 "schannel": "4", 692 "channel_list": "[]", 693 "period": strconv.Itoa(period), 694 "pwd": pwd, 695 "share_type": "9", 696 }, map[string]string{ 697 "Content-Type": "application/x-www-form-urlencoded", 698 }) 699 return 700 } 701 702 // PrepareShareCancel 取消分享, 只返回服务器响应数据和错误信息 703 func (pcs *BaiduPCS) PrepareShareCancel(shareIDs []int64) (dataReadCloser io.ReadCloser, panError pcserror.Error) { 704 pcs.lazyInit() 705 panURL := &url.URL{ 706 Scheme: "https", 707 Host: PanBaiduCom, 708 Path: "share/cancel", 709 } 710 711 baiduPCSVerbose.Infof("%s URL: %s\n", OperationShareCancel, panURL) 712 713 ss := converter.SliceInt64ToString(shareIDs) 714 dataReadCloser, panError = pcs.sendReqReturnReadCloser(reqTypePan, OperationShareCancel, http.MethodPost, panURL.String(), map[string]string{ 715 "shareid_list": "[" + strings.Join(ss, ",") + "]", 716 }, map[string]string{ 717 "Content-Type": "application/x-www-form-urlencoded", 718 }) 719 return 720 } 721 722 // PrepareShareList 列出分享列表, 只返回服务器响应数据和错误信息 723 func (pcs *BaiduPCS) PrepareShareList(page int) (dataReadCloser io.ReadCloser, panError pcserror.Error) { 724 pcs.lazyInit() 725 726 query := url.Values{} 727 query.Set("page", strconv.Itoa(page)) 728 query.Set("desc", "1") 729 query.Set("order", "time") 730 731 panURL := &url.URL{ 732 Scheme: "https", 733 Host: PanBaiduCom, 734 Path: "share/record", 735 RawQuery: query.Encode(), 736 } 737 baiduPCSVerbose.Infof("%s URL: %s\n", OperationShareList, panURL) 738 739 dataReadCloser, panError = pcs.sendReqReturnReadCloser(reqTypePan, OperationShareList, http.MethodGet, panURL.String(), nil, nil) 740 return 741 } 742 743 // PrepareShareSURLInfo 获取分享的详细信息, 包含密码, 只返回服务器响应数据和错误信息 744 func (pcs *BaiduPCS) PrepareShareSURLInfo(shareID int64) (dataReadCloser io.ReadCloser, panError pcserror.Error) { 745 pcs.lazyInit() 746 747 query := url.Values{} 748 query.Set("shareid", strconv.FormatInt(shareID, 10)) 749 query.Set("sign", converter.ToString(netdisksign.ShareSURLInfoSign(shareID))) 750 751 panURL := &url.URL{ 752 Scheme: "https", 753 Host: PanBaiduCom, 754 Path: "share/surlinfoinrecord", 755 RawQuery: query.Encode(), 756 } 757 baiduPCSVerbose.Infof("%s URL: %s\n", OperationShareSURLInfo, panURL) 758 759 dataReadCloser, panError = pcs.sendReqReturnReadCloser(reqTypePan, OperationShareSURLInfo, http.MethodGet, panURL.String(), nil, nil) 760 return 761 } 762 763 // PrepareRecycleList 列出回收站文件列表, 只返回服务器响应数据和错误信息 764 func (pcs *BaiduPCS) PrepareRecycleList(page int) (dataReadCloser io.ReadCloser, panError pcserror.Error) { 765 pcs.lazyInit() 766 767 panURL := pcs.generatePanURL("recycle/list", map[string]string{ 768 "num": "100", 769 "page": strconv.Itoa(page), 770 }) 771 772 baiduPCSVerbose.Infof("%s URL: %s\n", OperationRecycleList, panURL) 773 774 dataReadCloser, panError = pcs.sendReqReturnReadCloser(reqTypePan, OperationRecycleList, http.MethodGet, panURL.String(), nil, nil) 775 return 776 } 777 778 // PrepareRecycleRestore 还原回收站文件或目录, 只返回服务器响应数据和错误信息 779 func (pcs *BaiduPCS) PrepareRecycleRestore(fidList ...int64) (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 780 pcs.lazyInit() 781 782 pcsURL := pcs.generatePCSURL("file", "restore") 783 baiduPCSVerbose.Infof("%s URL: %s\n", OperationRecycleRestore, pcsURL) 784 785 fsIDList := make([]*FsIDJSON, 0, len(fidList)) 786 for k := range fidList { 787 fsIDList = append(fsIDList, &FsIDJSON{ 788 FsID: fidList[k], 789 }) 790 } 791 fsIDListJSON := FsIDListJSON{ 792 List: fsIDList, 793 } 794 795 sendData, err := jsoniter.Marshal(&fsIDListJSON) 796 if err != nil { 797 panic(err) 798 } 799 800 // 表单上传 801 mr := multipartreader.NewMultipartReader() 802 mr.AddFormFeild("param", bytes.NewReader(sendData)) 803 mr.CloseMultipart() 804 805 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationRecycleRestore, http.MethodPost, pcsURL.String(), mr, nil) 806 return 807 } 808 809 // PrepareRecycleDelete 删除回收站文件或目录, 只返回服务器响应数据和错误信息 810 func (pcs *BaiduPCS) PrepareRecycleDelete(fidList ...int64) (dataReadCloser io.ReadCloser, panError pcserror.Error) { 811 pcs.lazyInit() 812 813 panURL := pcs.generatePanURL("recycle/delete", nil) 814 baiduPCSVerbose.Infof("%s URL: %s\n", OperationRecycleDelete, panURL) 815 816 dataReadCloser, panError = pcs.sendReqReturnReadCloser(reqTypePan, OperationRecycleDelete, http.MethodPost, panURL.String(), map[string]string{ 817 "fidlist": mergeInt64List(fidList...), 818 }, map[string]string{ 819 "Content-Type": "application/x-www-form-urlencoded", 820 }) 821 return 822 } 823 824 // PrepareRecycleClear 清空回收站, 只返回服务器响应数据和错误信息 825 func (pcs *BaiduPCS) PrepareRecycleClear() (dataReadCloser io.ReadCloser, pcsError pcserror.Error) { 826 pcs.lazyInit() 827 828 pcsURL := pcs.generatePCSURL("file", "delete", map[string]string{ 829 "type": "recycle", 830 }) 831 832 baiduPCSVerbose.Infof("%s URL: %s\n", OperationRecycleClear, pcsURL) 833 834 dataReadCloser, pcsError = pcs.sendReqReturnReadCloser(reqTypePCS, OperationRecycleClear, http.MethodGet, pcsURL.String(), nil, nil) 835 return 836 }