github.com/fzfile/BaiduPCS-Go@v0.0.0-20200606205115-4408961cf336/internal/pcsfunctions/pcsupload/upload.go (about) 1 package pcsupload 2 3 import ( 4 "context" 5 "github.com/fzfile/BaiduPCS-Go/baidupcs" 6 "github.com/fzfile/BaiduPCS-Go/baidupcs/pcserror" 7 "github.com/fzfile/BaiduPCS-Go/internal/pcsconfig" 8 "github.com/fzfile/BaiduPCS-Go/requester" 9 "github.com/fzfile/BaiduPCS-Go/requester/multipartreader" 10 "github.com/fzfile/BaiduPCS-Go/requester/rio" 11 "github.com/fzfile/BaiduPCS-Go/requester/uploader" 12 "io" 13 "net/http" 14 ) 15 16 type ( 17 PCSUpload struct { 18 pcs *baidupcs.BaiduPCS 19 targetPath string 20 } 21 22 EmptyReaderLen64 struct { 23 } 24 ) 25 26 func (e EmptyReaderLen64) Read(p []byte) (n int, err error) { 27 return 0, io.EOF 28 } 29 30 func (e EmptyReaderLen64) Len() int64 { 31 return 0 32 } 33 34 func NewPCSUpload(pcs *baidupcs.BaiduPCS, targetPath string) uploader.MultiUpload { 35 return &PCSUpload{ 36 pcs: pcs, 37 targetPath: targetPath, 38 } 39 } 40 41 func (pu *PCSUpload) lazyInit() { 42 if pu.pcs == nil { 43 pu.pcs = &baidupcs.BaiduPCS{} 44 } 45 } 46 47 // Precreate do nothing 48 func (pu *PCSUpload) Precreate() (err error) { 49 return nil 50 } 51 52 func (pu *PCSUpload) TmpFile(ctx context.Context, partseq int, partOffset int64, r rio.ReaderLen64) (checksum string, uperr error) { 53 pu.lazyInit() 54 55 var respErr *uploader.MultiError 56 checksum, pcsError := pu.pcs.UploadTmpFile(func(uploadURL string, jar http.CookieJar) (resp *http.Response, err error) { 57 client := pcsconfig.Config.PCSHTTPClient() 58 client.SetCookiejar(jar) 59 client.SetTimeout(0) 60 61 mr := multipartreader.NewMultipartReader() 62 mr.AddFormFile("uploadedfile", "", r) 63 mr.CloseMultipart() 64 65 doneChan := make(chan struct{}, 1) 66 go func() { 67 resp, err = client.Req(http.MethodPost, uploadURL, mr, nil) 68 doneChan <- struct{}{} 69 70 if resp != nil { 71 // 不可恢复的错误 72 switch resp.StatusCode { 73 case 400, 401, 403, 413: 74 respErr = &uploader.MultiError{ 75 Terminated: true, 76 } 77 } 78 } 79 }() 80 select { 81 case <-ctx.Done(): // 取消 82 // 返回, 让那边关闭连接 83 return resp, ctx.Err() 84 case <-doneChan: 85 // return 86 } 87 return 88 }) 89 90 if respErr != nil { 91 respErr.Err = pcsError 92 return checksum, respErr 93 } 94 95 return checksum, pcsError 96 } 97 98 func (pu *PCSUpload) CreateSuperFile(checksumList ...string) (err error) { 99 pu.lazyInit() 100 101 // 先在网盘目标位置, 上传一个空文件 102 // 防止出现file does not exist 103 pcsError := pu.pcs.Upload(pu.targetPath, func(uploadURL string, jar http.CookieJar) (resp *http.Response, err error) { 104 mr := multipartreader.NewMultipartReader() 105 mr.AddFormFile("file", "file", &EmptyReaderLen64{}) 106 mr.CloseMultipart() 107 108 c := requester.NewHTTPClient() 109 c.SetCookiejar(jar) 110 return c.Req(http.MethodPost, uploadURL, mr, nil) 111 }) 112 if pcsError != nil { 113 // 修改操作 114 pcsError.(*pcserror.PCSErrInfo).Operation = baidupcs.OperationUploadCreateSuperFile 115 return pcsError 116 } 117 118 return pu.pcs.UploadCreateSuperFile(false, pu.targetPath, checksumList...) 119 }