-
-
Notifications
You must be signed in to change notification settings - Fork 26
/
object_part.go
271 lines (251 loc) · 10.8 KB
/
object_part.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
package cos
import (
"context"
"encoding/xml"
"fmt"
"io"
"net/http"
)
// InitiateMultipartUploadOptions ...
type InitiateMultipartUploadOptions struct {
*ACLHeaderOptions
*ObjectPutHeaderOptions
}
// InitiateMultipartUploadResult ...
type InitiateMultipartUploadResult struct {
XMLName xml.Name `xml:"InitiateMultipartUploadResult"`
// 分片上传的目标 Bucket,由用户自定义字符串和系统生成appid数字串由中划线连接而成,如:mybucket-1250000000
Bucket string
// Object 的名称
Key string
// 在后续上传中使用的 ID
UploadID string `xml:"UploadId"`
}
// MethodObjectInitiateMultipartUpload method name of Object.InitiateMultipartUpload
const MethodObjectInitiateMultipartUpload MethodName = "Object.InitiateMultipartUpload"
// InitiateMultipartUpload ...
//
// Initiate Multipart Upload请求实现初始化分片上传,成功执行此请求以后会返回Upload ID用于后续的Upload Part请求。
//
// https://cloud.tencent.com/document/product/436/7746
func (s *ObjectService) InitiateMultipartUpload(ctx context.Context, name string, opt *InitiateMultipartUploadOptions) (*InitiateMultipartUploadResult, *Response, error) {
var res InitiateMultipartUploadResult
sendOpt := sendOptions{
baseURL: s.client.BaseURL.BucketURL,
uri: "/" + encodeURIComponent(name) + "?uploads",
method: http.MethodPost,
optHeader: opt,
result: &res,
caller: Caller{
Method: MethodObjectInitiateMultipartUpload,
},
}
resp, err := s.client.send(ctx, &sendOpt)
return &res, resp, err
}
// ObjectUploadPartOptions ...
type ObjectUploadPartOptions struct {
// RFC 2616 中定义的 HTTP 请求内容长度(字节)
Expect string `header:"Expect,omitempty" url:"-"`
XCosContentSHA1 string `header:"x-cos-content-sha1" url:"-"`
// RFC 1864 中定义的经过Base64编码的128-bit 内容 MD5 校验值。此头部用来校验文件内容是否发生变化
ContentMD5 string `header:"Content-MD5" url:"-"`
// RFC 2616 中定义的 HTTP 请求内容长度(字节)
ContentLength int `header:"Content-Length,omitempty" url:"-"`
}
// MethodObjectUploadPart method name of Object.UploadPart
const MethodObjectUploadPart MethodName = "Object.UploadPart"
// UploadPart ...
//
// Upload Part 接口请求实现将对象按照分块的方式上传到 COS。
// 最多支持 10000 分块,每个分块大小为 1 MB 到 5 GB ,最后一个分块可以小于 1 MB。
//
// 细节分析
//
// * 分块上传首先需要进行初始化,使用 Initiate Multipart Upload 接口实现,初始化后会得到一个 uploadId ,唯一标识本次上传;
// * 在每次请求 Upload Part 时,需要携带 partNumber 和 uploadId,partNumber 为块的编号,支持乱序上传;
// * 当传入 uploadId 和 partNumber 都相同的时候,后传入的块将覆盖之前传入的块。当 uploadId 不存在时会返回 404 错误,NoSuchUpload。
//
// 当 r 是个 io.ReadCloser 时 UploadPart 方法不会自动调用 r.Close(),用户需要自行选择合适的时机去调用 r.Close() 方法对 r 进行资源回收
//
// https://cloud.tencent.com/document/product/436/7750
func (s *ObjectService) UploadPart(ctx context.Context, name, uploadID string, partNumber int, r io.Reader, opt *ObjectUploadPartOptions) (*Response, error) {
u := fmt.Sprintf("/%s?partNumber=%d&uploadId=%s", encodeURIComponent(name), partNumber, uploadID)
sendOpt := sendOptions{
baseURL: s.client.BaseURL.BucketURL,
uri: u,
method: http.MethodPut,
optHeader: opt,
body: r,
caller: Caller{
Method: MethodObjectUploadPart,
},
}
resp, err := s.client.send(ctx, &sendOpt)
return resp, err
}
// ObjectListPartsOptions ...
type ObjectListPartsOptions struct {
// 规定返回值的编码方式
EncodingType string `url:"Encoding-type,omitempty"`
// 单次返回最大的条目数量,默认1000
MaxParts int `url:"max-parts,omitempty"`
// 默认以 UTF-8 二进制顺序列出条目,所有列出条目从 marker 开始
PartNumberMarker int `url:"part-number-marker,omitempty"`
}
// ObjectListPartsResult ...
//
// https://cloud.tencent.com/document/product/436/7747
type ObjectListPartsResult struct {
XMLName xml.Name `xml:"ListPartsResult"`
// 分块上传的目标 Bucket,存储桶的名字,由用户自定义字符串和系统生成 appid 数字串由中划线连接而成,
// 如:mybucket-1250000000
Bucket string
// 编码格式
EncodingType string `xml:"Encoding-type,omitempty"`
// Object 的名字
Key string
// 标识本次分块上传的 ID
UploadID string `xml:"UploadId"`
// 用来表示这些分块所有者的信息
Initiator *Initiator `xml:"Initiator,omitempty"`
// 用来表示这些分块所有者的信息
Owner *Owner `xml:"Owner,omitempty"`
// 用来表示这些分块的存储级别,枚举值:STANDARD,STANDARD_IA,ARCHIVE
StorageClass string
// 默认以 UTF-8 二进制顺序列出条目,所有列出条目从 marker 开始
PartNumberMarker int
// 假如返回条目被截断,则返回 NextMarker 就是下一个条目的起点
NextPartNumberMarker int `xml:"NextPartNumberMarker,omitempty"`
// 单次返回最大的条目数量
MaxParts int
// 响应请求条目是否被截断,布尔值:true,false
IsTruncated bool
// 元数据信息
Parts []Object `xml:"Part,omitempty"`
}
// MethodObjectListParts method name of Object.ListParts
const MethodObjectListParts MethodName = "Object.ListParts"
// ListParts ...
//
// List Parts 用来查询特定分块上传中的已上传的块,即罗列出指定 UploadId 所属的所有已上传成功的分块。
//
// https://cloud.tencent.com/document/product/436/7747
func (s *ObjectService) ListParts(ctx context.Context, name, uploadID string) (*ObjectListPartsResult, *Response, error) {
u := fmt.Sprintf("/%s?uploadId=%s", encodeURIComponent(name), uploadID)
var res ObjectListPartsResult
sendOpt := sendOptions{
baseURL: s.client.BaseURL.BucketURL,
uri: u,
method: http.MethodGet,
result: &res,
caller: Caller{
Method: MethodObjectListParts,
},
}
resp, err := s.client.send(ctx, &sendOpt)
return &res, resp, err
}
// MethodObjectListPartsWithOpt method name of Object.ListPartsWithOpt
const MethodObjectListPartsWithOpt MethodName = "Object.ListPartsWithOpt"
// ListPartsWithOpt ...
//
// ListParts 方法的补充,解决 ListParts 不支持指定参数的问题。
// List Parts 用来查询特定分块上传中的已上传的块,即罗列出指定 UploadId 所属的所有已上传成功的分块。
//
// https://cloud.tencent.com/document/product/436/7747
func (s *ObjectService) ListPartsWithOpt(ctx context.Context, name, uploadID string, opt *ObjectListPartsOptions) (*ObjectListPartsResult, *Response, error) {
u := fmt.Sprintf("/%s?uploadId=%s", encodeURIComponent(name), uploadID)
var res ObjectListPartsResult
sendOpt := sendOptions{
baseURL: s.client.BaseURL.BucketURL,
uri: u,
method: http.MethodGet,
optQuery: opt,
result: &res,
caller: Caller{
Method: MethodObjectListPartsWithOpt,
},
}
resp, err := s.client.send(ctx, &sendOpt)
return &res, resp, err
}
// CompleteMultipartUploadOptions ...
//
// https://cloud.tencent.com/document/product/436/7742
type CompleteMultipartUploadOptions struct {
XMLName xml.Name `xml:"CompleteMultipartUpload"`
Parts []Object `xml:"Part"`
}
// CompleteMultipartUploadResult ...
//
// https://cloud.tencent.com/document/product/436/7742
type CompleteMultipartUploadResult struct {
XMLName xml.Name `xml:"CompleteMultipartUploadResult"`
// 创建的Object的外网访问域名
Location string
// 分块上传的目标Bucket,由用户自定义字符串和系统生成appid数字串由中划线连接而成,
// 如:mybucket-1250000000
Bucket string
// Object的名称
Key string
// 合并后对象的唯一标签值,该值不是对象内容的 MD5 校验值,仅能用于检查对象唯一性
ETag string
}
// MethodObjectCompleteMultipartUpload method name of Object.CompleteMultipartUpload
const MethodObjectCompleteMultipartUpload MethodName = "Object.CompleteMultipartUpload"
// CompleteMultipartUpload ...
//
// Complete Multipart Upload用来实现完成整个分块上传。当您已经使用Upload Parts上传所有块以后,你可以用该API完成上传。
// 在使用该API时,您必须在Body中给出每一个块的PartNumber和ETag,用来校验块的准确性。
//
// 由于分块上传的合并需要数分钟时间,因而当合并分块开始的时候,COS就立即返回200的状态码,在合并的过程中,
// COS会周期性的返回空格信息来保持连接活跃,直到合并完成,COS会在Body中返回合并后块的内容。
//
// 当上传块小于1 MB的时候,在调用该请求时,会返回400 EntityTooSmall;
// 当上传块编号不连续的时候,在调用该请求时,会返回400 InvalidPart;
// 当请求Body中的块信息没有按序号从小到大排列的时候,在调用该请求时,会返回400 InvalidPartOrder;
// 当UploadId不存在的时候,在调用该请求时,会返回404 NoSuchUpload。
//
// 建议您及时完成分块上传或者舍弃分块上传,因为已上传但是未终止的块会占用存储空间进而产生存储费用。
//
// https://cloud.tencent.com/document/product/436/7742
func (s *ObjectService) CompleteMultipartUpload(ctx context.Context, name, uploadID string, opt *CompleteMultipartUploadOptions) (*CompleteMultipartUploadResult, *Response, error) {
u := fmt.Sprintf("/%s?uploadId=%s", encodeURIComponent(name), uploadID)
var res CompleteMultipartUploadResult
sendOpt := sendOptions{
baseURL: s.client.BaseURL.BucketURL,
uri: u,
method: http.MethodPost,
body: opt,
result: &res,
caller: Caller{
Method: MethodObjectCompleteMultipartUpload,
},
}
resp, err := s.client.send(ctx, &sendOpt)
return &res, resp, err
}
// MethodObjectAbortMultipartUpload method name of Object.AbortMultipartUpload
const MethodObjectAbortMultipartUpload MethodName = "Object.AbortMultipartUpload"
// AbortMultipartUpload ...
//
// Abort Multipart Upload 用来实现舍弃一个分块上传并删除已上传的块。当您调用 Abort Multipart Upload 时,
// 如果有正在使用这个Upload Parts上传块的请求,则Upload Parts会返回失败。当该UploadID不存在时,会返回404 NoSuchUpload。
//
// 建议您及时完成分块上传或者舍弃分块上传,因为已上传但是未终止的块会占用存储空间进而产生存储费用。
//
// https://cloud.tencent.com/document/product/436/7740
func (s *ObjectService) AbortMultipartUpload(ctx context.Context, name, uploadID string) (*Response, error) {
u := fmt.Sprintf("/%s?uploadId=%s", encodeURIComponent(name), uploadID)
sendOpt := sendOptions{
baseURL: s.client.BaseURL.BucketURL,
uri: u,
method: http.MethodDelete,
caller: Caller{
Method: MethodObjectAbortMultipartUpload,
},
}
resp, err := s.client.send(ctx, &sendOpt)
return resp, err
}