212
微信
下载文件__Java-SDK_SDK 参考_对象存储 OSS-阿里云
OSS Java SDK提供了丰富的文件下载接口,用户可以通过以下方式从OSS中下载文件:
- 流式下载
- 下载到本地文件
- 断点续传下载
- 范围下载
流式下载
在进行大文件下载时,往往不希望一次性处理全部内容,而是希望流式地处理,一次处理一部分内容。
提示:
- 流式下载的完整代码请参考:GitHub
// endpoint以杭州为例,其它region请按实际情况填写
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// accessKey请登录https://ak-console.aliyun.com/#/查看
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";
String bucketName = "<yourBucketName>";
// 创建OSSClient实例
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
OSSObject ossObject = ossClient.getObject(bucketName, "yourKey");
// 读Object内容
System.out.println("Object content:");
BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
while (true) {
String line = reader.readLine();
if (line == null) break;
System.out.println("n" + line);
}
reader.close();
// 关闭client
ossClient.shutdown();
提示:
- OSSObject实例包含文件所在的存储空间(Bucket)、文件的名称、Object Metadata以及一个输入流;
- 通过操作输入流将文件的内容读取到文件或者内存中。而Object Metadata包含ETag、HTTP Header及自定义的元信息;
- OSSClient.getObject获取的流一定要显示close,否则会造成资源泄露;
OSSObject ossObject = ossClient.getObject(bucketName, key);
ossObject.getObjectContent().close();
- 假如需要从OSS流式读取64KB的数据,请使用如下的方式多次读取,直到读取64KB或者文件结束:
而不是如下的形式:
byte[] buf = new byte[1024];
InputStream in = ossObject.getObjectContent();
for (int n = 0; n != -1; ) {
n = in.read(buf, 0, buf.length);
}
in.close();
原因是,流式读取一次不一定能读到全部数据,详细说明请参考 InputStream.read 。
byte[] buf = new byte[64 * 1024];
InputStream in = ossObject.getObjectContent();
in.read(buf, 0, buf.length);
in.close();
下载到本地文件
把Object的内容下载到指定的本地文件中。如果指定的本地文件不存在则会新建。
// endpoint以杭州为例,其它region请按实际情况填写
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// accessKey请登录https://ak-console.aliyun.com/#/查看
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";
String bucketName = "<yourBucketName>";
// 创建OSSClient实例
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
// 下载object到文件
ossClient.getObject(new GetObjectRequest(bucketName, "<yourKey>"), new File("<yourLocalFile>"));
// 关闭client
ossClient.shutdown();
范围下载
如果OSS文件较大,并且只需要其中一部分数据,可以使用范围下载,下载指定范围的数据。如果指定的下载范围是0 - 100,则返回第0到第100个字节的数据,包括第100个,共101字节的数据,即[0, 100]。如果指定的范围无效,则传送整个文件。
// endpoint以杭州为例,其它region请按实际情况填写
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// accessKey请登录https://ak-console.aliyun.com/#/查看
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";
String bucketName = "<yourBucketName>";
// 创建OSSClient实例
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, "<yourKey>");
// 获取0~1000字节范围内的数据,包括0和1000,共1001个字节的数据
getObjectRequest.setRange(0, 1000);
// 范围下载
OSSObject ossObject = ossClient.getObject(getObjectRequest);
// 读取数据
byte[] buf = new byte[1024];
InputStream in = ossObject.getObjectContent();
for (int n = 0; n != -1; ) {
n = in.read(buf, 0, buf.length);
}
// InputStream数据读完成后,一定要close,否则会造成连接泄漏
in.close();
// 关闭client
ossClient.shutdown();
提示:
- 如果指定的Range无效(比如开始位置、结束位置为负数,大于文件大小),则会下载整个文件;
- 假如需要从OSS流式读取64KB的数据,请使用如下的方式多次读取,直到读取64KB或者文件结束:
而不是如下的形式:
byte[] buf = new byte[1024];
InputStream in = ossObject.getObjectContent();
for (int n = 0; n != -1; ) {
n = in.read(buf, 0, buf.length);
}
in.close();
原因是,流式读取一次不一定能读到全部数据,详细说明请参考 InputStream.read 。
byte[] buf = new byte[64 * 1024];
InputStream in = ossObject.getObjectContent();
in.read(buf, 0, buf.length);
in.close();
断点续传下载
当下载大文件时,如果网络不稳定或者程序崩溃了,则整个下载就失败了。用户不得不重头再来,这样做不仅浪费资源,在网络不稳定的情况下,往往重试多次还是无法完成下载。通过OSSClient.downloadFile
接口来实现断点续传分片下载,参数是DownloadFileRequest
,该请求有以下参数:
- bucket 存储空间名字,必选参数,通过构造方法设置
- key 下载到OSS的Object名字,必选参数,通过构造方法设置
- downloadFile 本地文件,下载到该文件,可选参数,默认是key,通过构造方法或setDownloadFile设置
- partSize 分片大小,从1B到5GB,单位是Byte,可选参数,默认100K,通过setPartSize设置
- taskNum 分片下载并发数,可选参数,默认为1,通过setTaskNum设置
- enableCheckpoint 下载是否开启断点续传,可选参数,默认断点续传功能关闭,通过setEnableCheckpoint设置
- checkpointFile 开启断点续传时,需要在本地记录分片下载结果,如果下载失败,下次不会再下载已经成功的分片,可选参数,默认与downloadFile同目录,为
downloadFile.ucp
,可以通过setCheckpointFile设置
其实现的原理是将要下载的Object分成若干个分片分别下载,最后所有分片都下载成功后,完成整个文件的下载。在下载的过程中会记录当前下载的进度信息(记录在checkpoint文件中)和已下载的分片,如果下载过程中某一分片下载失败,再次下载时会从checkpoint文件中记录的点继续下载。这要求再次调用时要指定与上次相同的checkpoint文件。下载完成后,checkpoint文件会被删除。
// endpoint以杭州为例,其它region请按实际情况填写
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// accessKey请登录https://ak-console.aliyun.com/#/查看
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";
String bucketName = "<yourBucketName>";
// 创建OSSClient实例
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
// 下载请求,10个任务并发下载,启动断点续传
DownloadFileRequest downloadFileRequest = new DownloadFileRequest("bucketName", "key");
downloadFileRequest.setDownloadFile("downloadFile");
downloadFileRequest.setTaskNum(10);
downloadFileRequest.setEnableCheckpoint(true);
// 下载文件
DownloadFileResult downloadRes = ossClient.downloadFile(downloadFileRequest);
// 下载成功时,会返回文件的元信息
downloadRes.getObjectMetadata();
// 关闭client
ossClient.shutdown();
限定条件下载
下载文件时,可以指定一个或多个限定条件,满足限定条件时下载,不满足时报错,不下载文件。可以使用的限定条件如下:
参数 | 说明 |
---|---|
If-Modified-Since | 如果指定的时间早于实际修改时间,则正常传送。否则返回错误。 |
If-Unmodified-Since | 如果传入参数中的时间等于或者晚于文件实际修改时间,则正常传输文件;否则返回错误。 |
If-Match | 如果传入期望的ETag和object的 ETag匹配,则正常传输;否则返回错误。 |
If-None-Match | 如果传入的ETag值和Object的ETag不匹配,则正常传输;否则返回错误。 |
注意:
- 如果If-Modified-Since设定的时间不符合规范,直接返回文件,并返回200 OK;
- If-Modified-Since和If-Unmodified-Since可以同时存在,If-Match和If-None-Match也可以同时存在;
- 如果包含If-Unmodified-Since并且不符合或者包含If-Match并且不符合,返回412 precondition failed;
- 如果包含If-Modified-Since并且不符合或者包含If-None-Match并且不符合,返回304 Not Modified。
// endpoint以杭州为例,其它region请按实际情况填写
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// accessKey请登录https://ak-console.aliyun.com/#/查看
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";
String bucketName = "<yourBucketName>";
// 创建OSSClient实例
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
GetObjectRequest request = new GetObjectRequest(bucketName, "<yourKey>");
request.setModifiedSinceConstraint(new Date());
// 下载object到文件
ossClient.getObject(request, new File("<yourLocalFile>"));
// 关闭client
ossClient.shutdown();
提示:
- ETag的值可以通过OSSClient.getObjectMetadata获取;
- OSSClient.getObject,OSSClient.downloadFile都支持限定条件。
下载进度条
OSS Java sdk支持进度条功能,指示上传/下载的进度。下面的代码以OSSClient.getObject为例,说明进度条功能的使用。
提示:
- 下载进度条的完整代码请参考:GitHub
static class GetObjectProgressListener implements ProgressListener {
private long bytesRead = 0;
private long totalBytes = -1;
private boolean succeed = false;
@Override
public void progressChanged(ProgressEvent progressEvent) {
long bytes = progressEvent.getBytes();
ProgressEventType eventType = progressEvent.getEventType();
switch (eventType) {
case TRANSFER_STARTED_EVENT:
System.out.println("Start to download......");
break;
case RESPONSE_CONTENT_LENGTH_EVENT:
this.totalBytes = bytes;
System.out.println(this.totalBytes + " bytes in total will be downloaded to a local file");
break;
case RESPONSE_BYTE_TRANSFER_EVENT:
this.bytesRead += bytes;
if (this.totalBytes != -1) {
int percent = (int)(this.bytesRead * 100.0 / this.totalBytes);
System.out.println(bytes + " bytes have been read at this time, download progress: " +
percent + "%(" + this.bytesRead + "/" + this.totalBytes + ")");
} else {
System.out.println(bytes + " bytes have been read at this time, download ratio: unknown" +
"(" + this.bytesRead + "/...)");
}
break;
case TRANSFER_COMPLETED_EVENT:
this.succeed = true;
System.out.println("Succeed to download, " + this.bytesRead + " bytes have been transferred in total");
break;
case TRANSFER_FAILED_EVENT:
System.out.println("Failed to download, " + this.bytesRead + " bytes have been transferred");
break;
default:
break;
}
}
public boolean isSucceed() {
return succeed;
}
}
public static void main(String[] args) {
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
String accessKeyId = "<accessKeyId>";
String accessKeySecret = "<accessKeySecret>";
String bucketName = "<bucketName>";
String key = "object-get-progress-sample";
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
try {
// 带进度条的下载
client.getObject(new GetObjectRequest(bucketName, key).
<GetObjectRequest>withProgressListener(new GetObjectProgressListener()),
new File("<yourLocalFile>"));
} catch (Exception e) {
e.printStackTrace();
}
ossClient.shutdown();
}
提示:
- putObject/getObject/uploadPart都支持进度条功能;
- uploadFile/downloadFile不支持进度条功能。
最后更新:2016-11-23 16:04:10
上一篇:
管理Bucket__Java-SDK_SDK 参考_对象存储 OSS-阿里云
下一篇:
管理文件__Java-SDK_SDK 参考_对象存储 OSS-阿里云
OSSWriter__Writer插件_使用手册_数据集成-阿里云
安全组__网络和安全性_产品简介_云服务器 ECS-阿里云
限制说明__产品简介_云数据库 Memcache 版-阿里云
阿里云与中科院合作发布量子计算云平台,潘建伟透露研发目标
附录:PPAS 兼容性说明__快速入门(PPAS)_云数据库 RDS 版-阿里云
堡垒机__使用金融云产品_金融云-阿里云
新建测试___Lite用户使用手册_性能测试-阿里云
CreateLoadBalancerUDPListener__Listener相关API_API 参考_负载均衡-阿里云
如何参加线上培训课程__线上培训课程_上云培训-阿里云
分配公网 IP 地址__网络相关接口_API 参考_云服务器 ECS-阿里云
相关内容
常见错误说明__附录_大数据计算服务-阿里云
发送短信接口__API使用手册_短信服务-阿里云
接口文档__Android_安全组件教程_移动安全-阿里云
运营商错误码(联通)__常见问题_短信服务-阿里云
设置短信模板__使用手册_短信服务-阿里云
OSS 权限问题及排查__常见错误及排除_最佳实践_对象存储 OSS-阿里云
消息通知__操作指南_批量计算-阿里云
设备端快速接入(MQTT)__快速开始_阿里云物联网套件-阿里云
查询API调用流量数据__API管理相关接口_API_API 网关-阿里云
使用STS访问__JavaScript-SDK_SDK 参考_对象存储 OSS-阿里云