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  }