Skip to content

Commit 0bd92f8

Browse files
authored
Merge pull request #116 from agin719/cos-v4-dev
Cos v4 dev
2 parents 8a9f014 + 7a8d337 commit 0bd92f8

File tree

4 files changed

+99
-16
lines changed

4 files changed

+99
-16
lines changed

cos.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222

2323
const (
2424
// Version current go sdk version
25-
Version = "0.7.23"
25+
Version = "0.7.24"
2626
userAgent = "cos-go-sdk-v5/" + Version
2727
contentTypeXML = "application/xml"
2828
defaultServiceBaseURL = "http://service.cos.myqcloud.com"
@@ -71,7 +71,8 @@ func NewBucketURL(bucketName, region string, secure bool) *url.URL {
7171
}
7272

7373
type Config struct {
74-
EnableCRC bool
74+
EnableCRC bool
75+
RequestBodyClose bool
7576
}
7677

7778
// Client is a client manages communication with the COS API.
@@ -119,7 +120,8 @@ func NewClient(uri *BaseURL, httpClient *http.Client) *Client {
119120
UserAgent: userAgent,
120121
BaseURL: baseURL,
121122
Conf: &Config{
122-
EnableCRC: true,
123+
EnableCRC: true,
124+
RequestBodyClose: false,
123125
},
124126
}
125127
c.common.client = c
@@ -182,6 +184,9 @@ func (c *Client) newRequest(ctx context.Context, baseURL *url.URL, uri, method s
182184
if c.Host != "" {
183185
req.Host = c.Host
184186
}
187+
if c.Conf.RequestBodyClose {
188+
req.Close = true
189+
}
185190
return
186191
}
187192

helper.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
// 单次上传文件最大为5GB
1818
const singleUploadMaxLength = 5 * 1024 * 1024 * 1024
19+
const singleUploadThreshold = 32 * 1024 * 1024
1920

2021
// 计算 md5 或 sha1 时的分块大小
2122
const calDigestBlockSize = 1024 * 1024 * 10

object.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -217,14 +217,24 @@ func (s *ObjectService) Put(ctx context.Context, name string, r io.Reader, uopt
217217

218218
// PutFromFile put object from local file
219219
// Notice that when use this put large file need set non-body of debug req/resp, otherwise will out of memory
220-
func (s *ObjectService) PutFromFile(ctx context.Context, name string, filePath string, opt *ObjectPutOptions) (*Response, error) {
221-
fd, err := os.Open(filePath)
222-
if err != nil {
223-
return nil, err
220+
func (s *ObjectService) PutFromFile(ctx context.Context, name string, filePath string, opt *ObjectPutOptions) (resp *Response, err error) {
221+
nr := 0
222+
for nr < 3 {
223+
fd, e := os.Open(filePath)
224+
if e != nil {
225+
err = e
226+
return
227+
}
228+
resp, err = s.Put(ctx, name, fd, opt)
229+
if err != nil {
230+
nr++
231+
fd.Close()
232+
continue
233+
}
234+
fd.Close()
235+
break
224236
}
225-
defer fd.Close()
226-
227-
return s.Put(ctx, name, fd, opt)
237+
return
228238
}
229239

230240
// ObjectCopyHeaderOptions is the head option of the Copy
@@ -778,9 +788,12 @@ func (s *ObjectService) Upload(ctx context.Context, name string, filepath string
778788
}
779789
defer fd.Close()
780790
localcrc, err = calCRC64(fd)
791+
if err != nil {
792+
return nil, nil, err
793+
}
781794
}
782795
// filesize=0 , use simple upload
783-
if partNum == 0 {
796+
if partNum == 0 || partNum == 1 {
784797
var opt0 *ObjectPutOptions
785798
if opt.OptIni != nil {
786799
opt0 = &ObjectPutOptions{

object_test.go

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -375,13 +375,13 @@ func TestObjectService_Upload(t *testing.T) {
375375
}
376376
defer os.Remove(filePath)
377377
// 源文件内容
378-
b := make([]byte, 1024*1024*10)
378+
b := make([]byte, 1024*1024*33)
379379
_, err = rand.Read(b)
380380
newfile.Write(b)
381381
newfile.Close()
382382

383383
// 已上传内容, 10个分块
384-
rb := make([][]byte, 10)
384+
rb := make([][]byte, 33)
385385
uploadid := "test-cos-multiupload-uploadid"
386386
partmap := make(map[int64]int)
387387
mux.HandleFunc("/test.go.upload", func(w http.ResponseWriter, r *http.Request) {
@@ -423,9 +423,7 @@ func TestObjectService_Upload(t *testing.T) {
423423
// 完成分块上传
424424
tb := crc64.MakeTable(crc64.ECMA)
425425
crc := uint64(0)
426-
ccv := make([]uint64, 10)
427-
for i, v := range rb {
428-
ccv[i] = crc64.Update(0, crc64.MakeTable(crc64.ECMA), v)
426+
for _, v := range rb {
429427
crc = crc64.Update(crc, tb, v)
430428
}
431429
w.Header().Add("x-cos-hash-crc64ecma", strconv.FormatUint(crc, 10))
@@ -450,3 +448,69 @@ func TestObjectService_Upload(t *testing.T) {
450448
t.Fatalf("Object.Upload returned error: %v", err)
451449
}
452450
}
451+
452+
func TestObjectService_Upload2(t *testing.T) {
453+
setup()
454+
defer teardown()
455+
456+
filePath := "tmpfile" + time.Now().Format(time.RFC3339)
457+
newfile, err := os.Create(filePath)
458+
if err != nil {
459+
t.Fatalf("create tmp file failed")
460+
}
461+
defer os.Remove(filePath)
462+
// 源文件内容
463+
b := make([]byte, 1024*1024*3)
464+
_, err = rand.Read(b)
465+
newfile.Write(b)
466+
newfile.Close()
467+
468+
tb := crc64.MakeTable(crc64.ECMA)
469+
realcrc := crc64.Update(0, tb, b)
470+
name := "test/hello.txt"
471+
retry := 0
472+
final := 4
473+
mux.HandleFunc("/test/hello.txt", func(w http.ResponseWriter, r *http.Request) {
474+
testMethod(t, r, http.MethodPut)
475+
testHeader(t, r, "x-cos-acl", "private")
476+
testHeader(t, r, "Content-Type", "text/html")
477+
478+
if retry%2 == 0 {
479+
bs, _ := ioutil.ReadAll(r.Body)
480+
crc := crc64.Update(0, tb, bs)
481+
if !reflect.DeepEqual(bs, b) {
482+
t.Errorf("Object.Put request body Error")
483+
}
484+
if !reflect.DeepEqual(crc, realcrc) {
485+
t.Errorf("Object.Put crc: %v, want: %v", crc, realcrc)
486+
}
487+
w.Header().Add("x-cos-hash-crc64ecma", strconv.FormatUint(crc, 10))
488+
if retry != final {
489+
w.WriteHeader(http.StatusGatewayTimeout)
490+
}
491+
} else {
492+
w.Header().Add("x-cos-hash-crc64ecma", "123456789")
493+
}
494+
})
495+
496+
mopt := &MultiUploadOptions{
497+
OptIni: &InitiateMultipartUploadOptions{
498+
ObjectPutHeaderOptions: &ObjectPutHeaderOptions{
499+
ContentType: "text/html",
500+
},
501+
ACLHeaderOptions: &ACLHeaderOptions{
502+
XCosACL: "private",
503+
},
504+
},
505+
}
506+
for retry <= final {
507+
_, _, err := client.Object.Upload(context.Background(), name, filePath, mopt)
508+
if retry < final && err == nil {
509+
t.Fatalf("Error must not nil when retry < final")
510+
}
511+
if retry == final && err != nil {
512+
t.Fatalf("Put Error: %v", err)
513+
}
514+
retry++
515+
}
516+
}

0 commit comments

Comments
 (0)