github.com/qjfoidnh/BaiduPCS-Go@v0.0.0-20231011165705-caa18a3765f3/internal/pcsfunctions/pcsupload/upload.go (about) 1 package pcsupload 2 3 import ( 4 "context" 5 "github.com/qjfoidnh/BaiduPCS-Go/baidupcs" 6 "github.com/qjfoidnh/BaiduPCS-Go/baidupcs/pcserror" 7 "github.com/qjfoidnh/BaiduPCS-Go/internal/pcsconfig" 8 "github.com/qjfoidnh/BaiduPCS-Go/requester" 9 "github.com/qjfoidnh/BaiduPCS-Go/requester/multipartreader" 10 "github.com/qjfoidnh/BaiduPCS-Go/requester/rio" 11 "github.com/qjfoidnh/BaiduPCS-Go/requester/uploader" 12 "io" 13 "net/http" 14 "time" 15 ) 16 17 type ( 18 PCSUpload struct { 19 pcs *baidupcs.BaiduPCS 20 targetPath string 21 } 22 23 EmptyReaderLen64 struct { 24 } 25 ) 26 27 var client *requester.HTTPClient = pcsconfig.Config.PCSHTTPClient() 28 29 func (e EmptyReaderLen64) Read(p []byte) (n int, err error) { 30 return 0, io.EOF 31 } 32 33 func (e EmptyReaderLen64) Len() int64 { 34 return 0 35 } 36 37 func NewPCSUpload(pcs *baidupcs.BaiduPCS, targetPath string) uploader.MultiUpload { 38 return &PCSUpload{ 39 pcs: pcs, 40 targetPath: targetPath, 41 } 42 } 43 44 func (pu *PCSUpload) lazyInit() { 45 if pu.pcs == nil { 46 pu.pcs = &baidupcs.BaiduPCS{} 47 } 48 } 49 50 // Precreate 检查网盘的目标路径是否已存在同名文件及路径合法性 51 func (pu *PCSUpload) Precreate(fileSize int64, policy string) pcserror.Error { 52 pcsError := pu.pcs.CheckIsdir(baidupcs.OperationUpload, pu.targetPath, policy, fileSize) 53 return pcsError 54 } 55 56 func (pu *PCSUpload) TmpFile(ctx context.Context, partseq int, partOffset int64, r rio.ReaderLen64) (checksum string, uperr error) { 57 pu.lazyInit() 58 59 var respErr *uploader.MultiError 60 checksum, pcsError := pu.pcs.UploadTmpFile(func(uploadURL string, jar http.CookieJar) (resp *http.Response, err error) { 61 //client := pcsconfig.Config.PCSHTTPClient() 62 client.SetCookiejar(jar) 63 client.SetTimeout(200 * time.Second) 64 65 mr := multipartreader.NewMultipartReader() 66 mr.AddFormFile("uploadedfile", "", r) 67 mr.CloseMultipart() 68 69 doneChan := make(chan struct{}, 1) 70 go func() { 71 resp, err = client.Req(http.MethodPost, uploadURL, mr, nil) 72 doneChan <- struct{}{} 73 74 if resp != nil { 75 // 不可恢复的错误 76 switch resp.StatusCode { 77 case 400, 401, 403, 413: // 4xx通常是由客户端非法操作引发,直接深度重试 78 respErr = &uploader.MultiError{ 79 Terminated: true, 80 } 81 } 82 } 83 }() 84 select { 85 case <-ctx.Done(): // 取消 86 // 返回, 让那边关闭连接 87 return resp, ctx.Err() 88 case <-doneChan: 89 // return 90 } 91 return 92 }) 93 94 if respErr != nil { 95 respErr.Err = pcsError 96 return checksum, respErr 97 } 98 99 return checksum, pcsError 100 } 101 102 func (pu *PCSUpload) CreateSuperFile(policy string, checksumList ...string) (err error) { 103 pu.lazyInit() 104 //newpath := "" 105 // 先在网盘目标位置, 上传一个空文件 106 // 防止出现file does not exist 107 pcsError, newpath := pu.pcs.Upload(policy, pu.targetPath, func(uploadURL string, jar http.CookieJar) (resp *http.Response, err error) { 108 mr := multipartreader.NewMultipartReader() 109 mr.AddFormFile("file", "file", &EmptyReaderLen64{}) 110 mr.CloseMultipart() 111 112 c := requester.NewHTTPClient() 113 c.SetCookiejar(jar) 114 return c.Req(http.MethodPost, uploadURL, mr, nil) 115 }) 116 if pcsError != nil { 117 // 修改操作 118 pcsError.(*pcserror.PCSErrInfo).Operation = baidupcs.OperationUploadCreateSuperFile 119 return pcsError 120 } 121 122 // 此时已到了最后的合并环节,policy只能使用overwrite, newpath而不用pu.targetPath是因为newcopy策略可能导致文件名变化 123 //return pu.pcs.UploadCreateSuperFile("overwrite",false, pu.targetPath, checksumList...) 124 return pu.pcs.UploadCreateSuperFile("overwrite",false, newpath, checksumList...) 125 }