高级接口
实例化ArchiveManager
++ArchiveManager++是高级接口的入口,包含上传和下载两类接口,每一个接口均包含阻塞和异步两种实现,其中方法名以Async结尾的为异步方法。所有接口均可能抛出两种异常,分别为++OASClientException++和++OASServerException++,详见本章异常一节。
++ArchiveManager++的可通过如下三种方式获得:
// 使用默认配置
ServiceCredentials credentials = new ServiceCredentials(
"[yourAccessKeyID]", "[yourAccessKeySecret]");
ArchiveManager archiveManager = OASFactory.archiveManagerFactory(credentials,
"http://cn-hangzhou.oas.aliyuncs.com");
//初始化认证
ServiceCredentials credentials = new ServiceCredentials(
"[yourAccessKeyId]", "[yourAccessKeySecret]");
//服务地址
ServiceHost serviceHost = new ServiceHost("http://cn-hangzhou.oas.aliyuncs.com", 80);
//客户端配置
ClientConfiguration clientConfiguration = new ClientConfiguration();
ArchiveManager archiveManager = new ArchiveManager(serviceHost, credentials, clientConf);
// 使用AliyunOASClient初始化
AliyunOASClient aliyunOASClient = OASFactory.aliyunOASClientFactory(
serviceHost, credentials, clientConfiguration).withLogger();
ArchiveManager archiveManager = OASFactory.archiveManagerFactory(aliyunOASClient);
其中,ClientConfiguration的具体使用请参阅本章最后一节自定义配置,AliyunOASClient的具体介绍参见 《OAS Java SDK低级接口文档》。为使示例更简洁,本章示例中若出现未定义的archiveManager变量,均是指ArchiveManager对象。
在Multipart上传、大文件下载时,多线程可以提高执行效率,高级接口提供让用户指定线程并发数量:
// 设置多线程并发数为5,默认:3,最大:10
// 设置单上传链路重试次数,默认为2,最大:3
ArchiveManager manager = OASFactory.archiveManagerFactory(
credentials,
"http://cn-hangzhou.oas.aliyuncs.com"
).withNumConcurrence(5).withMaxRetryTimePerRequest(3);
注:为避免文档中代码的冗长,本文设计的样例代码,会省去ArchiveManager的实例化。
配置ArchiveManager
同步接口和异步接口
ArchiveManager中按交互模式,分成同步接口(阻塞式)和异步接口(非阻塞)两大类。同步接口会阻塞当前运行的程序,异步接口则反之。在使用过程中,建议使用异步接口,通过实现监听类来获取任务中间状态。 用户很容易通过方法的名称来区分这两类接口,比如:
- upload(...) 即为同步式上传接口
- uploadAsync(...) 即为异步式上传接口
下面的章节,将通过业务类型的划分,来分别介绍各种业务接口的具体定义。
上传Archive
普通上传
用户通过接口上传文件到指定名称的Vault,可选的description参数是Archive的描述字段。使用普通上传接口时,用户无需关心是否开启Multipart,SDK会根据文件的大小选择适合用户的方式进行上传,两个普通上传接口定义如下:
/**
* 上传文件到指定的vault中
* @param vaultName
* 目标vault的名称
* @param file
* 需要上传的文件对象
* @return 返回UploadResult对象
* @throws OASClientException
* 客户端异常
* @throws OASServerException
* 服务端异常
*/
public UploadResult upload(String vaultName, File file)
throws OASClientException, OASServerException;
/**
* 上传文件到指定的vault中
* @param vaultName
* 目标vault的名称
* @param file
* 需要上传的文件对象
* @param description
* 上传archive的备注
* @return 返回UploadResult对象
* @throws OASClientException
* 客户端异常
* @throws OASServerException
* 服务端异常
*/
public UploadResult upload(String vaultName, File file, String description)
throws OASClientException, OASServerException;
文件上传示例:
File file = new File("[pathToYourFile]");
ServiceCredentials credentials = new ServiceCredentials(
DemoConstants.ACCESS_ID,
DemoConstants.ACCESS_KEY);
// 通过工厂类获得archiveManager接口
ArchiveManager archiveManager = OASFactory.archiveManagerFactory(credentials);
// java sdk 会帮助用户完成 vaultName 到 vaultId 的转换
// 由此避免了用户对一长串vaultId的记忆负担
UploadResult result = archiveManager
.upload("[yourVaultName]", file, "[Description(not necessary)]");
String archiveId = result.getArchiveId();
System.out.println("Archive ID=" + archiveId);
注:上述的两个upload接口,已能满足用户的大部分需求
使用Multipart进行上传
用户可以指定使用Multipart模式进行上传,完成一个Multipart上传需要两步:
- 初始化Multipart上传,获得UploadId
- 根据获得的UploadId,上传数据
关于UploadId的定义和作用,请参考 《OAS API文档》-4.3.1章节初始化Multipart Upload任务 中的详细介绍。
涉及到的接口定义如下:
/**
* 手工初始化Multipart上传任务
* @param vaultName 目标vault名称
* @param file 需要上传的文件
* @return 初始化成功的Multipart上传任务的UploadId字符串
* @throws OASClientException
* @throws OASServerException
*/
public String initiateMultipartUpload(String vaultName, File file)
throws OASClientException, OASServerException;
/**
* 手工初始化Multipart上传任务
* @param vaultName 目标vault名称
* @param file 需要上传的文件
* @param description 文件描述
* @return 初始化成功的Multipart上传任务的UploadId字符串
* @throws OASClientException
* @throws OASServerException
*/
public String initiateMultipartUpload(String vaultName, File file, String description)
throws OASClientException, OASServerException;
/**
* 根据具体的UploadId上传文件。
* 要配合 {@link initiateMultipartUpload} 使用
* @param vaultName 目标vault名称
* @param file 需要上传的文件
* @param uploadId 初始化完成的Multipart的UploadId
* @return 上传结果对象
* @throws OASClientException
* @throws OASServerException
*/
public UploadResult uploadWithUploadId(String vaultName, File file, String uploadId)
throws OASClientException, OASServerException;
示例代码:
File file = new File("[pathToYourFile]");
String vaultName = "[yourVaultName]";
//获得uploadId
//文件大小必须大于100MB,否则会抛异常提示用普通上传接口进行上传
String uploadId = archiveManager.initiateMultipartUpload(vaultName, file, "Hello OAS!");
//如果是已有的uploadId,直接使用之前获取过的uploadId
//String uploadId = "[uploadIdYouAlreadyHave]";
System.out.println("Get uploadId=" + uploadId);
UploadResult uploadResult = archiveManager.uploadWithUploadId(vaultName, file, uploadId);
System.out.println("Archive ID=" + uploadResult.getArchiveId());
使用已有的uploadId进行再次上传时,支持该任务的续传。例如,当一个Multipart任务在上传过程中被中止,这时,一些part已上传到OAS,一些part未完成。只要文件内容没有变化,根据保存下来的uploadId,可以继续上传这个文件剩余的part,已上传完毕的part不会重复上传。
如果开启了logger功能(如何配置logger请参考 《OAS Java SDK低级接口文档》),在日志中会看到以下信息:
....
Range 33554432-67108863 got from OAS server, contentEtag=BEC7D9E8EC48FFD9C3859C10B64B4EDF, treeEtag=8DA41EA468F5613080A3D14857EFEFFE
Range 33554432-67108863 has uploaded, contentEtag=BEC7D9E8EC48FFD9C3859C10B64B4EDF, treeEtag=8DA41EA468F5613080A3D14857EFEFFE
Range 33554432-67108863 is the same as remote,ignore it. md5=BEC7D9E8EC48FFD9C3859C10B64B4EDF,etagTree=8DA41EA468F5613080A3D14857EFEFFE
....
只有当这个part的md5和etagTree的校验信息一致时,SDK才会忽略它的上传动作,否则,这个part会被重传。日志中会出现
....
Range 33554432-67108863 local Etag data is different from remote. It will be uploaded again!
....
下载
在OAS服务协议中,下载是通过提交任务(Job)的形式存在的,按业务类型分为三类,分别是:
- 提交下载Archive任务
- 提交下载Inventory任务
- 下载Job输出
用户需要提交Job来获得他需要的数据,一个Job从创建到完成需要经历三步骤:
- 用户 通过接口提交相应类型的Job;
- OAS 接收到Job并安排其执行;
- 用户 将已完成Job的输出内容下载到本地。
注:Job在OAS服务端是异步执行的,一个Job从提交到执行完毕这个过程一般耗时在几分钟到四小时之间。所以,所有下载类接口都是 异步接口 即全部以 Async 结尾。更多关于Job的信息,参考《OAS API文档 4.4 Job 操作》。
提交下载Archive Job
接口定义如下:
/**
* 提交请求下载archive任务请求
* @param vaultName 目标vault名称
* @param archiveId 需下载的archiveId
* @return 返回Job信息跟踪器,可用来获取Job信息,如jobId,eTag校验信息
* @throws OASClientException
* @throws OASServerException
*/
public JobMonitor downloadAsync(String vaultName, String archiveId)
throws OASClientException, OASServerException;
/**
* 提交请求下载archive任务请求
* @param vaultName 目标vault名称
* @param archiveId 需下载的archiveId
* @param description 备注
* @return 返回Job信息跟踪器,可用来获取Job信息,如jobId,eTag校验信息
* @throws OASClientException
* @throws OASServerException
*/
public JobMonitor downloadAsync(String vaultName, String archiveId, String description)
throws OASClientException, OASServerException;
/**
* 提交请求下载archive任务请求
* @param vaultName 目标vault名称
* @param archiveId 需下载的archiveId
* @param range 指定要下载的范围
* @return 返回Job信息跟踪器,可用来获取Job信息,如jobId,eTag校验信息
* @throws OASClientException
* @throws OASServerException
*/
public JobMonitor downloadWithRangeAsync(String vaultName, String archiveId, Range range)
throws OASClientException, OASServerException;
/**
* 提交请求下载archive任务请求
* @param vaultName 目标vault名称
* @param archiveId 需下载的archiveId
* @param range 指定要下载的范围
* @param description 备注
* @return 返回Job信息跟踪器,可用来获取Job信息,如jobId,eTag校验信息
* @throws OASClientException
* @throws OASServerException
*/
public JobMonitor downloadWithRangeAsync(
String vaultName, String archiveId, Range range, String description)
throws OASClientException, OASServerException;
示例代码:
JobMonitor jobMonitor = archiveManager.downloadAsync(
"[yourVaultName]", "[yourArchiveId]");
// JobMonitor提供的阻塞等待方法,直到Job状态完结
// 实际场景中,不建议如此使用,因为Job的执行时间在几分钟到4小时不等
// 长时间阻塞程序不是明智的做法
jobMonitor.waitUntilFinished();
System.out.println("Job has been comitted successfully.");
System.out.println("Your JobId=" + jobMonitor.getJobId());
关于JobMonitor的具体使用方法,请阅读本文档 下载 章节的最后一部分 JobMonitor类使用讲解
提交Inventory任务
根据给定的Vault的名称, 提交Iventory任务后,OAS将准备好该Vault所包含文件的最后一次扫描信息,待Job执行完毕,可以将Vault的文件信息下载到本地。接口定义:
/**
* 根据vault名称获得vault的目录信息
* @param vaultName 目标vault名称
* @return
*/
public JobMonitor downloadInventoryAsync(String vaultName)
throws OASClientException, OASServerException;
/**
* 根据vault名称获得vault的目录信息
* @param vaultName 目标vault名称
* @param description 备注
* @return
* @throws OASClientException
* @throws OASServerException
*/
public JobMonitor downloadInventoryAsync(
String vaultName, String description)
throws OASClientException, OASServerException;
下载Job输出
根据给定的 Vault名称 和 JobID,下载Job的结果至本地文件。接口定义:
/**
* 下载Job输出到文件,只有当Job的状态是Succeeded或Failed(到达终结状态)时,才能执行此操作
* @param vaultName 目标vault名称
* @param jobId 要下载的jobId
* @param file 保存的目标文件
* @return 保存的目标文件的句柄对象
* @throws OASClientException
* @throws OASServerException
*/
public File downloadJobOutput(String vaultName, String jobId, File file)
throws OASClientException, OASServerException;
/**
* 下载Job输出到文件,只有当Job的状态是Succeeded或Failed(到达终结状态)时,才能执行此操作
* @param vaultName 目标vault名称
* @param jobId 要下载的jobId
* @param file 保存的目标文件
* @return 异步任务传输对象,可获得传输信息
* @throws OASClientException
* @throws OASServerException
*/
public BaseTransfer<File> downloadJobOutputAsync(
String vaultName, String jobId, File file)
throws OASClientException, OASServerException;
JobMonitor类使用讲解
所有的下载动作,都是通过提交Job、下载Job输出的步骤完成。JobMonitor类是OAS JAVA SDK封装好,供用户跟踪Job信息的类,下面对JobMonitor类具体使用进行介绍。
waitUntilFinished()方法: 功能:阻塞住程序,每个1分钟请求OAS服务更新JobMonitor中Job的状态,直到Job的状态为 成功 或者 失败,取消阻塞,例如下面的代码,虽然这样使用是==不推荐==的:
// JobMonitor提供的阻塞等待方法,直到Job状态完结 // 注意,本方法不建议用户使用,因为一个Job从提交到完成,一般需要几分钟到4个小时不等 // 长期阻塞程序,不是一个明智的选择 // 这里的使用仅仅起到示例作用 jobMonitor.waitUntilFinished(); System.out.println("Job has ended."); System.out.println("JobId=" + jobMonitor.getJobId() + ", JobStatus=" + jobMonitor.getJobStatus() + ", TreeEtag=" + jobMonitor.getDescriptor().getTreeEtag());
checkJobFinishedWithRefresh()方法: 功能:向OAS服务发送一个请求,获取Job的最新状态,并判断最新状态是否为 成功、失败 中的一个,如果是,返回ture,否则返回false,示例代码如下,由于也会长期阻塞程序,这种用法也是 不推荐 的;
while (true) { if (jobMonitor.checkJobFinishedWithRefresh()) { System.out.println("Job has ended."); System.out.println("JobId=" + jobMonitor.getJobId() + ", JobStatus=" + jobMonitor.getJobStatus() + ", TreeEtag=" + jobMonitor.getDescriptor().getTreeEtag()); break; } else { try { Thread.sleep(1000); } catch (InterruptedException e) { logger.error("ERROR!", e); } } }
推荐的JobMonitor的使用方法: 当使用ArchiveManager提交了Job后,可以从接口返回的JobMonitor中实时获取到本次任务的jobId,同样,ArchiveManager也提供了接口,根据jobId和vaultName实例化JobMonitor的方法:
/** * 实例化JobMonitor * @param vaultName 目标vault名称 * @param jobId 要实例化的jobId * @return * @throws OASClientException * @throws OASServerException */ public JobMonitor getJobMonitor(String vaultName, String jobId) throws OASClientException, OASServerException;
JobMonitor的实例化可以在用户程序的任何地方,随后用checkJobFinishedWithRefresh()等方法来检查Job的状态是否扭转,几个推荐的使用场景:
- 定时执行的任务中 (例如:可以每个小时扫描上一小时提交的Job的状态,再对Job输出进行下载);
- 某些业务事件被触发后(例如:业务中依赖这次Job输出的内容,否则该业务事件就无法执行);
- 用户触发。
其他getter方法: 该类中有很多get方法,可以获得JobId(getJobId()方法)、JobStatus(getJobStatus()方法)等信息,但是这些方法获得的仅仅是本地的缓存,有可能和OAS服务端的信息不一致,如果需要手动从OAS服务端获取最新信息,可以执行 refreshJobDescriptorFromRemote()方法来实现。
异步接口中间过程的监听
异步接口与同步接口不同的是方法的返回值,一般来说,返回的对象是BaseTransfer,用户可通过ProgressListener监听进度,SpeedListener监听速度,通过start开始任务,stop停止任务,而waitUntilFinished将会阻塞直至任务完成,getResult可获取上传或下载结果。具体使用请参考本节的示例。
ProgressListener、SpeedListener和JobStatusListener分别为进度、速度、任务状态监听器,各个监听器的每个接口含义见下文的例子,而ProgressListenerAdapter、SpeedListenerAdapter和JobStatusListenerAdapter分别实现了以上接口,出错时默认会自动重试3次。特别注意的是,监听器部分接口的调用是在IO线程中,在监听器中执行费时的操作将有可能导致网络连接出错甚至中断。
以上传为例
ServiceCredentials credentials = new ServiceCredentials(
DemoConstants.ACCESS_ID,
DemoConstants.ACCESS_KEY);
// 通过工厂类获得archiveManager接口
ArchiveManager archiveManager = OASFactory.archiveManagerFactory(credentials);
File file = new File("[pathToYourFile]");
final BaseTransfer<UploadResult> bt = archiveManager.uploadAsync(
"[yourVaultName]", file);
//设置最大并发数,默认为3,最大为10
bt.setNumConcurrence(5);
bt.addProgressListener(new ProgressListener() {
@Override
public void onStart(String id) {
// 任务开始时调用,其中id为Multipart Upload任务ID,对于一般上传任务id为空
System.out.println("Start! Upload ID: " + id);
}
@Override
public boolean onError(Range range, Throwable t) {
// 出错时调用,range是出错的字节范围,t是相应的错误
// 当返回true时,BaseTransfer会进行重试,false则放弃
System.out.println("ERROR!!!");
return false;
}
@Override
public void onCompleted() {
// 任务完成时调用
System.out.println("Upload complete");
}
@Override
public void onProgressed(long current, long total) {
// 上传进度,total为文件字节大小,current为当前已上传字节数
System.out.println("Progress: " + current + " / " + total);
}
});
bt.start();
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("Running time: " + bt.getRunningTime() + " seconds");
System.out.println("Completed size: " + bt.getSizeCompleted() + " bytes");
System.out.println("Total size: " + bt.getSizeTotal() + " bytes");
System.out.println("Average speed: " + bt.getAverageSpeedInBytesPerSecond()
+ " B/s");
if (bt.isComplete()) {
timer.cancel();
synchronized (bt) {
bt.notify();
}
}
}
}, 0, 1000);
synchronized (bt) {
try {
bt.wait();
} catch (InterruptedException e) {
logger.error("", e);
}
}
// 任务结束
System.out.println("=============================");
System.out.println("Running time: " + bt.getRunningTime() + " seconds");
System.out.println("Completed size: " + bt.getSizeCompleted() + " bytes");
System.out.println("Total size: " + bt.getSizeTotal() + " bytes");
System.out.println("Average speed: " + bt.getAverageSpeedInBytesPerSecond() + " B/s");
UploadResult uploadResult = bt.getResult();
System.out.println("Archive ID: " + uploadResult.getArchiveId());
System.out.println("ContentEtag: " + uploadResult.getContentEtag());
异常
根据出错原因的不同,SDK把异常分为两种不同类型,分别为OAServerError和OASClientError。
OASServerError
OASServerException是指一次完整的HTTP请求中,服务器返回了错误响应。各个成员变量的含义见下表。具体错误信息请参阅API文档第5节错误响应。
成员变量 | 类型 | 含义 |
---|---|---|
statusCode | int | HTTP状态码 |
requestId | String | 出错的请求的ID值,见API文档2.3.3节 |
errorCode | String | 错误代码,见API文档2.3.3节 |
errorMessage | String | 错误信息,见API文档2.3.3节 |
errorType | ErrorType | 错误类型,见API文档2.3.3节 |
OASClientErrror
OASClientException表示客户端异常,可能原因包括网络连接出错、文件读写出错等,具体出错原因可通过查看成员变量message获得。异常仅作为标记错误类型,没有实现额外的方法。
自定义配置
高级接口ArchiveManager和低级接口AliyunOASClient一样,支持配置自定义,ServiceHost和ClientConfiguration的具体配置参考《OAS Java SDK低级接口文档》
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。
评论