@@ -332,6 +332,9 @@ type ObjectPutHeaderOptions struct {
332332type ObjectPutOptions struct {
333333 * ACLHeaderOptions `header:",omitempty" url:"-" xml:"-"`
334334 * ObjectPutHeaderOptions `header:",omitempty" url:"-" xml:"-"`
335+
336+ // PutFromFile 使用
337+ innerSwitchURL * url.URL `header:"-" url:"-" xml:"-"`
335338}
336339
337340// Put Object请求可以将一个文件(Oject)上传至指定Bucket。
@@ -358,27 +361,56 @@ func (s *ObjectService) Put(ctx context.Context, name string, r io.Reader, uopt
358361 opt .ContentLength = totalBytes
359362 }
360363 }
361- reader := TeeReader (r , nil , totalBytes , nil )
362- if s .client .Conf .EnableCRC {
363- reader .writer = crc64 .New (crc64 .MakeTable (crc64 .ECMA ))
364- }
365- if opt != nil && opt .Listener != nil {
366- reader .listener = opt .Listener
367- }
368- sendOpt := sendOptions {
369- baseURL : s .client .BaseURL .BucketURL ,
370- uri : "/" + encodeURIComponent (name ),
371- method : http .MethodPut ,
372- body : reader ,
373- optHeader : opt ,
364+ // 如果是io.Seeker,则重试
365+ count := 1
366+ var position int64
367+ if seeker , ok := r .(io.Seeker ); ok {
368+ // 记录原始位置
369+ position , err = seeker .Seek (0 , io .SeekCurrent )
370+ if err == nil && s .client .Conf .RetryOpt .Count > 0 {
371+ count = s .client .Conf .RetryOpt .Count
372+ }
373+ }
374+ var resp * Response
375+ var retrieable bool
376+ sUrl := s .client .BaseURL .BucketURL
377+ if opt .innerSwitchURL != nil {
378+ sUrl = opt .innerSwitchURL
379+ }
380+ for nr := 0 ; nr < count ; nr ++ {
381+ reader := TeeReader (r , nil , totalBytes , nil )
382+ if s .client .Conf .EnableCRC {
383+ reader .writer = crc64 .New (crc64 .MakeTable (crc64 .ECMA ))
384+ }
385+ if opt != nil && opt .Listener != nil {
386+ reader .listener = opt .Listener
387+ }
388+ sendOpt := sendOptions {
389+ baseURL : sUrl ,
390+ uri : "/" + encodeURIComponent (name ),
391+ method : http .MethodPut ,
392+ body : reader ,
393+ optHeader : opt ,
394+ }
395+ resp , err = s .client .send (ctx , & sendOpt )
396+ sUrl , retrieable = s .client .CheckRetrieable (sUrl , resp , err )
397+ if retrieable && nr + 1 < count {
398+ if seeker , ok := r .(io.Seeker ); ok {
399+ _ , e := seeker .Seek (position , io .SeekStart )
400+ if e != nil {
401+ break
402+ }
403+ continue
404+ }
405+ }
406+ break
374407 }
375- resp , err := s .client .send (ctx , & sendOpt )
376-
377408 return resp , err
378409}
379410
380411// PutFromFile put object from local file
381- func (s * ObjectService ) PutFromFile (ctx context.Context , name string , filePath string , opt * ObjectPutOptions ) (resp * Response , err error ) {
412+ func (s * ObjectService ) PutFromFile (ctx context.Context , name string , filePath string , uopt * ObjectPutOptions ) (resp * Response , err error ) {
413+ opt := CloneObjectPutOptions (uopt )
382414 nr := 0
383415 for nr < 3 {
384416 fd , e := os .Open (filePath )
@@ -390,6 +422,12 @@ func (s *ObjectService) PutFromFile(ctx context.Context, name string, filePath s
390422 if err != nil {
391423 nr ++
392424 fd .Close ()
425+ if s .client .Conf .RetryOpt .AutoSwitchHost {
426+ // 收不到报文 或者 不存在RequestId
427+ if resp == nil || resp .Header .Get ("X-Cos-Request-Id" ) == "" {
428+ opt .innerSwitchURL = toSwitchHost (s .client .BaseURL .BucketURL )
429+ }
430+ }
393431 continue
394432 }
395433 fd .Close ()
@@ -900,6 +938,12 @@ func worker(ctx context.Context, s *ObjectService, jobs <-chan *Jobs, results ch
900938 results <- & res
901939 break
902940 }
941+ if s .client .Conf .RetryOpt .AutoSwitchHost {
942+ // 收不到报文 或者 不存在RequestId
943+ if resp == nil || resp .Header .Get ("X-Cos-Request-Id" ) == "" {
944+ j .Opt .innerSwitchURL = toSwitchHost (s .client .BaseURL .BucketURL )
945+ }
946+ }
903947 time .Sleep (time .Millisecond )
904948 continue
905949 }
@@ -1128,6 +1172,7 @@ func (s *ObjectService) Upload(ctx context.Context, name string, filepath string
11281172 opt0 = & ObjectPutOptions {
11291173 opt .OptIni .ACLHeaderOptions ,
11301174 opt .OptIni .ObjectPutHeaderOptions ,
1175+ nil ,
11311176 }
11321177 }
11331178 rsp , err := s .PutFromFile (ctx , name , filepath , opt0 )
0 commit comments