Skip to content

Commit 4e15c6d

Browse files
authored
Merge pull request #207 from tencentyun/dev/checkPointUpload
delete check & range set
2 parents 80146eb + 2d7ddff commit 4e15c6d

File tree

6 files changed

+75
-126
lines changed

6 files changed

+75
-126
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>com.qcloud</groupId>
66
<artifactId>cos_api</artifactId>
7-
<version>5.6.219.1</version>
7+
<version>5.6.220</version>
88
<packaging>jar</packaging>
99
<name>cos-java-sdk</name>
1010
<description>java sdk for qcloud cos</description>

src/main/java/com/qcloud/cos/COSClient.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import java.util.List;
3939
import java.util.Map;
4040
import java.util.Map.Entry;
41+
import java.util.Objects;
4142

4243
import com.fasterxml.jackson.core.Version;
4344
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -143,6 +144,7 @@
143144
import com.qcloud.cos.utils.*;
144145
import com.qcloud.cos.http.TimeOutCosHttpClient;
145146

147+
import com.qcloud.cos.utils.Base64;
146148
import org.apache.commons.codec.DecoderException;
147149
import org.apache.http.client.methods.HttpRequestBase;
148150
import org.apache.http.entity.ContentType;
@@ -1072,8 +1074,16 @@ public COSObject getObject(GetObjectRequest getObjectRequest)
10721074
// Range
10731075
long[] range = getObjectRequest.getRange();
10741076
if (range != null) {
1075-
request.addHeader(Headers.RANGE,
1076-
"bytes=" + Long.toString(range[0]) + "-" + Long.toString(range[1]));
1077+
if (range[0] == -1) {
1078+
request.addHeader(Headers.RANGE,
1079+
"bytes=" + "-" + Long.toString(range[1]));
1080+
} else if (range[1] == -1) {
1081+
request.addHeader(Headers.RANGE,
1082+
"bytes=" + Long.toString(range[0]) + "-");
1083+
} else {
1084+
request.addHeader(Headers.RANGE,
1085+
"bytes=" + Long.toString(range[0]) + "-" + Long.toString(range[1]));
1086+
}
10771087
}
10781088
addResponseHeaderParameters(request, getObjectRequest.getResponseHeaders());
10791089

@@ -1274,6 +1284,11 @@ public void deleteObject(DeleteObjectRequest deleteObjectRequest)
12741284

12751285
rejectEmpty(deleteObjectRequest.getKey(),
12761286
"The length of the key must be greater than 0");
1287+
1288+
if (Objects.equals(deleteObjectRequest.getKey(), "/")) {
1289+
throw new IllegalArgumentException("The specified key should not be /");
1290+
}
1291+
12771292
CosHttpRequest<DeleteObjectRequest> request =
12781293
createRequest(deleteObjectRequest.getBucketName(), deleteObjectRequest.getKey(),
12791294
deleteObjectRequest, HttpMethodName.DELETE);

src/main/java/com/qcloud/cos/demo/TransferManagerDemo.java

Lines changed: 34 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,30 @@
3535
// TransferManager提供异步的上传文件, 下载文件,copy文件的高级API接口
3636
// 可以根据文件大小自动的选择上传接口或者copy接口,方便用户使用, 无需自行封装较复杂的分块上传或者分块copy
3737
public class TransferManagerDemo {
38+
private static String secretId = "AKIDXXXXXXXX";
39+
private static String secretKey = "1A2Z3YYYYYYYYYY";
40+
private static String cosRegion = "ap-guangzhou";
41+
private static String bucketName = "examplebucket-12500000000";
3842
public static void main(String[] args) {
3943
//multipartUploadWithMetaData();
4044
resumableDownloadFile();
4145
}
46+
47+
private static TransferManager createTransferManager() {
48+
// 1 初始化用户身份信息(secretId, secretKey)
49+
COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
50+
// 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
51+
ClientConfig clientConfig = new ClientConfig(new Region(cosRegion));
52+
clientConfig.setHttpProtocol(HttpProtocol.https);
53+
// 3 生成cos客户端
54+
COSClient cosclient = new COSClient(cred, clientConfig);
55+
56+
ExecutorService threadPool = Executors.newFixedThreadPool(32);
57+
// 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
58+
TransferManager transferManager = new TransferManager(cosclient, threadPool);
59+
return transferManager;
60+
}
61+
4262
// Prints progress while waiting for the transfer to finish.
4363
private static void showTransferProgress(Transfer transfer) {
4464
System.out.println(transfer.getDescription());
@@ -59,19 +79,7 @@ private static void showTransferProgress(Transfer transfer) {
5979

6080
// 上传文件, 根据文件大小自动选择简单上传或者分块上传。
6181
private static void uploadFile() {
62-
// 1 初始化用户身份信息(secretId, secretKey)
63-
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
64-
// 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
65-
ClientConfig clientConfig = new ClientConfig(new Region("ap-beijing-1"));
66-
clientConfig.setHttpProtocol(HttpProtocol.https);
67-
// 3 生成cos客户端
68-
COSClient cosclient = new COSClient(cred, clientConfig);
69-
// bucket名需包含appid
70-
String bucketName = "mybucket-12500000000";
71-
72-
ExecutorService threadPool = Executors.newFixedThreadPool(32);
73-
// 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
74-
TransferManager transferManager = new TransferManager(cosclient, threadPool);
82+
TransferManager transferManager = createTransferManager();
7583

7684
String key = "aaa/bbb.txt";
7785
File localFile = new File("src/test/resources/len30M.txt");
@@ -96,23 +104,11 @@ private static void uploadFile() {
96104
}
97105

98106
transferManager.shutdownNow();
99-
cosclient.shutdown();
100107
}
101108

102109
// 上传文件(上传过程中暂停, 并继续上传)
103110
private static void pauseUploadFileAndResume() {
104-
// 1 初始化用户身份信息(secretId, secretKey)
105-
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
106-
// 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
107-
ClientConfig clientConfig = new ClientConfig(new Region("ap-beijing-1"));
108-
// 3 生成cos客户端
109-
COSClient cosclient = new COSClient(cred, clientConfig);
110-
// bucket名需包含appid
111-
String bucketName = "mybucket-12500000000";
112-
113-
ExecutorService threadPool = Executors.newFixedThreadPool(4);
114-
// 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
115-
TransferManager transferManager = new TransferManager(cosclient, threadPool);
111+
TransferManager transferManager = createTransferManager();
116112

117113
String key = "aaa/bbb.txt";
118114
File localFile = new File("src/test/resources/len30M.txt");
@@ -135,22 +131,10 @@ private static void pauseUploadFileAndResume() {
135131
}
136132

137133
transferManager.shutdownNow();
138-
cosclient.shutdown();
139134
}
140135

141136
private static void multipartUploadWithMetaData() {
142-
// 1 初始化用户身份信息(secretId, secretKey)
143-
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
144-
// 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
145-
ClientConfig clientConfig = new ClientConfig(new Region("ap-shanghai"));
146-
// 3 生成cos客户端
147-
COSClient cosclient = new COSClient(cred, clientConfig);
148-
// bucket名需包含appid
149-
String bucketName = "mybucket-12500000000";
150-
151-
ExecutorService threadPool = Executors.newFixedThreadPool(2);
152-
// 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
153-
TransferManager transferManager = new TransferManager(cosclient, threadPool);
137+
TransferManager transferManager = createTransferManager();
154138

155139
String key = "aaa/bbb.txt";
156140
File localFile = new File("src/test/resources/len20M.txt");
@@ -181,23 +165,11 @@ private static void multipartUploadWithMetaData() {
181165
}
182166

183167
transferManager.shutdownNow();
184-
cosclient.shutdown();
185168
}
186169

187170
// 批量上传
188171
private static void uploadDirectory() {
189-
// 1 初始化用户身份信息(secretId, secretKey)
190-
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
191-
// 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
192-
ClientConfig clientConfig = new ClientConfig(new Region("ap-beijing-1"));
193-
// 3 生成cos客户端
194-
COSClient cosclient = new COSClient(cred, clientConfig);
195-
// bucket名需包含appid
196-
String bucketName = "mybucket-12500000000";
197-
198-
ExecutorService threadPool = Executors.newFixedThreadPool(4);
199-
// 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
200-
TransferManager transferManager = new TransferManager(cosclient, threadPool);
172+
TransferManager transferManager = createTransferManager();
201173

202174
// 设置文件上传到 bucket 之后的前缀目录,设置为 “”,表示上传到 bucket 的根目录
203175
String cos_path = "/prefix";
@@ -226,23 +198,11 @@ private static void uploadDirectory() {
226198
}
227199

228200
transferManager.shutdownNow();
229-
cosclient.shutdown();
230201
}
231202

232203
// 批量下载
233204
private static void downloadDirectory() {
234-
// 1 初始化用户身份信息(secretId, secretKey)
235-
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
236-
// 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
237-
ClientConfig clientConfig = new ClientConfig(new Region("ap-beijing-1"));
238-
// 3 生成cos客户端
239-
COSClient cosclient = new COSClient(cred, clientConfig);
240-
// bucket名需包含appid
241-
String bucketName = "mybucket-12500000000";
242-
243-
ExecutorService threadPool = Executors.newFixedThreadPool(4);
244-
// 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
245-
TransferManager transferManager = new TransferManager(cosclient, threadPool);
205+
TransferManager transferManager = createTransferManager();
246206

247207
// 设置要下载的对象的前缀(相当于cos上的一个目录),如果设置成 "",则下载整个 bucket。
248208
String cos_path = "/prefix";
@@ -269,23 +229,11 @@ private static void downloadDirectory() {
269229
}
270230

271231
transferManager.shutdownNow();
272-
cosclient.shutdown();
273232
}
274233

275234
// 将文件下载到本地
276235
private static void downLoadFile() {
277-
// 1 初始化用户身份信息(secretId, secretKey)
278-
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
279-
// 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
280-
ClientConfig clientConfig = new ClientConfig(new Region("ap-beijing-1"));
281-
// 3 生成cos客户端
282-
COSClient cosclient = new COSClient(cred, clientConfig);
283-
// bucket名需包含appid
284-
String bucketName = "mybucket-12500000000";
285-
286-
ExecutorService threadPool = Executors.newFixedThreadPool(32);
287-
// 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
288-
TransferManager transferManager = new TransferManager(cosclient, threadPool);
236+
TransferManager transferManager = createTransferManager();
289237

290238
String key = "aaa/bbb.txt";
291239
File downloadFile = new File("src/test/resources/download.txt");
@@ -303,23 +251,11 @@ private static void downLoadFile() {
303251
}
304252

305253
transferManager.shutdownNow();
306-
cosclient.shutdown();
307254
}
308255

309256
// 将文件下载到本地(中途暂停并继续开始)
310257
private static void pauseDownloadFileAndResume() {
311-
// 1 初始化用户身份信息(secretId, secretKey)
312-
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
313-
// 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
314-
ClientConfig clientConfig = new ClientConfig(new Region("ap-beijing-1"));
315-
// 3 生成cos客户端
316-
COSClient cosclient = new COSClient(cred, clientConfig);
317-
// bucket名需包含appid
318-
String bucketName = "mybucket-12500000000";
319-
320-
ExecutorService threadPool = Executors.newFixedThreadPool(32);
321-
// 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
322-
TransferManager transferManager = new TransferManager(cosclient, threadPool);
258+
TransferManager transferManager = createTransferManager();
323259

324260
String key = "aaa/bbb.txt";
325261
File downloadFile = new File("src/test/resources/download.txt");
@@ -340,23 +276,20 @@ private static void pauseDownloadFileAndResume() {
340276
e.printStackTrace();
341277
}
342278

343-
344279
transferManager.shutdownNow();
345-
cosclient.shutdown();
346280
}
347281

348282

349283
// copy接口支持根据文件大小自动选择copy或者分块copy
350284
// 以下代码展示跨园区拷贝, 即将一个园区的文件拷贝到另一个园区
351285
private static void copyFileForDiffRegion() {
352286
// 1 初始化用户身份信息(secretId, secretKey)
353-
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
287+
COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
354288
// 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
355-
ClientConfig clientConfig = new ClientConfig(new Region("ap-beijing-1"));
289+
ClientConfig clientConfig = new ClientConfig(new Region(cosRegion));
356290
// 3 生成cos客户端
357291
COSClient cosclient = new COSClient(cred, clientConfig);
358292

359-
360293
ExecutorService threadPool = Executors.newFixedThreadPool(32);
361294
// 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
362295
TransferManager transferManager = new TransferManager(cosclient, threadPool);
@@ -395,17 +328,7 @@ private static void copyFileForDiffRegion() {
395328
// copy接口支持根据文件大小自动选择copy或者分块copy
396329
// 以下代码展示同园区拷贝, 即将同园区的文件拷贝到另一个园区
397330
private static void copyFileForSameRegion() {
398-
// 1 初始化用户身份信息(secretId, secretKey)
399-
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
400-
// 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
401-
ClientConfig clientConfig = new ClientConfig(new Region("ap-beijing-1"));
402-
// 3 生成cos客户端
403-
COSClient cosclient = new COSClient(cred, clientConfig);
404-
405-
406-
ExecutorService threadPool = Executors.newFixedThreadPool(32);
407-
// 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
408-
TransferManager transferManager = new TransferManager(cosclient, threadPool);
331+
TransferManager transferManager = createTransferManager();
409332
TransferManagerConfiguration transferManagerConfiguration = new TransferManagerConfiguration();
410333
transferManagerConfiguration.setMultipartCopyThreshold(20*1024*1024);
411334
transferManager.setConfiguration(transferManagerConfiguration);
@@ -437,14 +360,13 @@ private static void copyFileForSameRegion() {
437360
}
438361

439362
transferManager.shutdownNow();
440-
cosclient.shutdown();
441363
}
442364

443365
private static void copyFileSetMetadata() {
444366
// 1 初始化用户身份信息(secretId, secretKey)
445-
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
367+
COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
446368
// 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
447-
ClientConfig clientConfig = new ClientConfig(new Region("ap-guangzhou"));
369+
ClientConfig clientConfig = new ClientConfig(new Region(cosRegion));
448370
// 3 生成cos客户端
449371
COSClient cosclient = new COSClient(cred, clientConfig);
450372

@@ -497,18 +419,9 @@ private static void copyFileSetMetadata() {
497419
}
498420

499421
private static void resumableDownloadFile() {
500-
// 1 初始化用户身份信息(secretId, secretKey)
501-
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
502-
// 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
503-
ClientConfig clientConfig = new ClientConfig(new Region("ap-shanghai"));
504-
// 3 生成cos客户端
505-
COSClient cosclient = new COSClient(cred, clientConfig);
422+
TransferManager transferManager = createTransferManager();
506423

507-
ExecutorService threadPool = Executors.newFixedThreadPool(5);
508-
// 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
509-
TransferManager transferManager = new TransferManager(cosclient, threadPool);
510-
511-
GetObjectRequest getObj = new GetObjectRequest("mybucket-1000000000", "/path/to/key");
424+
GetObjectRequest getObj = new GetObjectRequest(bucketName, "/path/to/key");
512425

513426
File dstFile = new File("dstFile");
514427
Download download = transferManager.download(getObj, dstFile, true);
@@ -524,6 +437,5 @@ private static void resumableDownloadFile() {
524437
}
525438

526439
transferManager.shutdownNow();
527-
cosclient.shutdown();
528440
}
529441
}

src/main/java/com/qcloud/cos/http/DefaultCosHttpClient.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,7 @@ public <X, Y extends CosServiceRequest> X exeute(CosHttpRequest<Y> request,
509509
}
510510
if (retryIndex != 0) {
511511
long delay = backoffStrategy.computeDelayBeforeNextRetry(retryIndex);
512+
request.addHeader("x-cos-sdk-retry", "true");
512513
Thread.sleep(delay);
513514
}
514515
HttpContext context = HttpClientContext.create();

src/main/java/com/qcloud/cos/model/GetObjectRequest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,20 @@ public void setRange(long start, long end) {
329329
range = new long[] {start, end};
330330
}
331331

332+
public void setRangeStart(long start) {
333+
if (start < 0) {
334+
throw new IllegalArgumentException("The range start should be greater than or equal to 0");
335+
}
336+
range = new long[] {start, -1L};
337+
}
338+
339+
public void setRangeEnd(long end) {
340+
if (end < 0) {
341+
throw new IllegalArgumentException("The range end should be greater than or equal to 0");
342+
}
343+
range = new long[] {-1L, end};
344+
}
345+
332346
/**
333347
* <p>
334348
* Sets the optional inclusive byte range within the desired object that will be downloaded by

src/main/java/com/qcloud/cos/transfer/TransferManager.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,7 @@ private Download doDownload(final GetObjectRequest getObjectRequest, final File
721721
long lastByte;
722722

723723
long[] range = getObjectRequest.getRange();
724-
if (range != null && range.length == 2) {
724+
if (range != null && range.length == 2 && range[0] != -1 && range[1] != -1) {
725725
startingByte = range[0];
726726
lastByte = range[1];
727727
} else {
@@ -734,6 +734,13 @@ private Download doDownload(final GetObjectRequest getObjectRequest, final File
734734
final ObjectMetadata objectMetadata = cos.getObjectMetadata(getObjectMetadataRequest);
735735

736736
lastByte = objectMetadata.getContentLength() - 1;
737+
if (range != null && range.length == 2) {
738+
if (range[0] == -1) {
739+
startingByte = lastByte - range[1] + 1;
740+
} else {
741+
startingByte = range[0];
742+
}
743+
}
737744
}
738745
final long origStartingByte = startingByte;
739746
// We still pass the unfiltered listener chain into DownloadImpl

0 commit comments

Comments
 (0)