高级接口

更新时间:2020-06-01 21:08:46

实例化ArchiveManager

++ArchiveManager++是高级接口的入口,包含上传和下载两类接口,每一个接口均包含阻塞和异步两种实现,其中方法名以Async结尾的为异步方法。所有接口均可能抛出两种异常,分别为++OASClientException++++OASServerException++,详见本章异常一节。

++ArchiveManager++的可通过如下三种方式获得:

  1. // 使用默认配置
  2. ServiceCredentials credentials = new ServiceCredentials(
  3. "[yourAccessKeyID]", "[yourAccessKeySecret]");
  4. ArchiveManager archiveManager = OASFactory.archiveManagerFactory(credentials,
  5. "http://cn-hangzhou.oas.aliyuncs.com");
  1. //初始化认证
  2. ServiceCredentials credentials = new ServiceCredentials(
  3. "[yourAccessKeyId]", "[yourAccessKeySecret]");
  4. //服务地址
  5. ServiceHost serviceHost = new ServiceHost("http://cn-hangzhou.oas.aliyuncs.com", 80);
  6. //客户端配置
  7. ClientConfiguration clientConfiguration = new ClientConfiguration();
  8. ArchiveManager archiveManager = new ArchiveManager(serviceHost, credentials, clientConf);
  1. // 使用AliyunOASClient初始化
  2. AliyunOASClient aliyunOASClient = OASFactory.aliyunOASClientFactory(
  3. serviceHost, credentials, clientConfiguration).withLogger();
  4. ArchiveManager archiveManager = OASFactory.archiveManagerFactory(aliyunOASClient);

其中,ClientConfiguration的具体使用请参阅本章最后一节自定义配置,AliyunOASClient的具体介绍参见 《OAS Java SDK低级接口文档》。为使示例更简洁,本章示例中若出现未定义的archiveManager变量,均是指ArchiveManager对象。

在Multipart上传、大文件下载时,多线程可以提高执行效率,高级接口提供让用户指定线程并发数量:

  1. // 设置多线程并发数为5,默认:3,最大:10
  2. // 设置单上传链路重试次数,默认为2,最大:3
  3. ArchiveManager manager = OASFactory.archiveManagerFactory(
  4. credentials,
  5. "http://cn-hangzhou.oas.aliyuncs.com"
  6. ).withNumConcurrence(5).withMaxRetryTimePerRequest(3);

注:为避免文档中代码的冗长,本文设计的样例代码,会省去ArchiveManager的实例化。

配置ArchiveManager

同步接口和异步接口

ArchiveManager中按交互模式,分成同步接口(阻塞式)和异步接口(非阻塞)两大类。同步接口会阻塞当前运行的程序,异步接口则反之。在使用过程中,建议使用异步接口,通过实现监听类来获取任务中间状态。用户很容易通过方法的名称来区分这两类接口,比如:

  1. upload(…) 即为同步式上传接口
  2. uploadAsync(…) 即为异步式上传接口

下面的章节,将通过业务类型的划分,来分别介绍各种业务接口的具体定义。

上传Archive

普通上传

用户通过接口上传文件到指定名称的Vault,可选的description参数是Archive的描述字段。使用普通上传接口时,用户无需关心是否开启Multipart,SDK会根据文件的大小选择适合用户的方式进行上传,两个普通上传接口定义如下:

  1. /**
  2. * 上传文件到指定的vault中
  3. * @param vaultName
  4. * 目标vault的名称
  5. * @param file
  6. * 需要上传的文件对象
  7. * @return 返回UploadResult对象
  8. * @throws OASClientException
  9. * 客户端异常
  10. * @throws OASServerException
  11. * 服务端异常
  12. */
  13. public UploadResult upload(String vaultName, File file)
  14. throws OASClientException, OASServerException;
  15. /**
  16. * 上传文件到指定的vault中
  17. * @param vaultName
  18. * 目标vault的名称
  19. * @param file
  20. * 需要上传的文件对象
  21. * @param description
  22. * 上传archive的备注
  23. * @return 返回UploadResult对象
  24. * @throws OASClientException
  25. * 客户端异常
  26. * @throws OASServerException
  27. * 服务端异常
  28. */
  29. public UploadResult upload(String vaultName, File file, String description)
  30. throws OASClientException, OASServerException;

文件上传示例:

  1. File file = new File("[pathToYourFile]");
  2. ServiceCredentials credentials = new ServiceCredentials(
  3. DemoConstants.ACCESS_ID,
  4. DemoConstants.ACCESS_KEY);
  5. // 通过工厂类获得archiveManager接口
  6. ArchiveManager archiveManager = OASFactory.archiveManagerFactory(credentials);
  7. // java sdk 会帮助用户完成 vaultName 到 vaultId 的转换
  8. // 由此避免了用户对一长串vaultId的记忆负担
  9. UploadResult result = archiveManager
  10. .upload("[yourVaultName]", file, "[Description(not necessary)]");
  11. String archiveId = result.getArchiveId();
  12. System.out.println("Archive ID=" + archiveId);

注:上述的两个upload接口,已能满足用户的大部分需求

使用Multipart进行上传

用户可以指定使用Multipart模式进行上传,完成一个Multipart上传需要两步:

  1. 初始化Multipart上传,获得UploadId
  2. 根据获得的UploadId,上传数据

关于UploadId的定义和作用,请参考 《OAS API文档》-4.3.1章节初始化Multipart Upload任务 中的详细介绍。

涉及到的接口定义如下:

  1. /**
  2. * 手工初始化Multipart上传任务
  3. * @param vaultName 目标vault名称
  4. * @param file 需要上传的文件
  5. * @return 初始化成功的Multipart上传任务的UploadId字符串
  6. * @throws OASClientException
  7. * @throws OASServerException
  8. */
  9. public String initiateMultipartUpload(String vaultName, File file)
  10. throws OASClientException, OASServerException;
  11. /**
  12. * 手工初始化Multipart上传任务
  13. * @param vaultName 目标vault名称
  14. * @param file 需要上传的文件
  15. * @param description 文件描述
  16. * @return 初始化成功的Multipart上传任务的UploadId字符串
  17. * @throws OASClientException
  18. * @throws OASServerException
  19. */
  20. public String initiateMultipartUpload(String vaultName, File file, String description)
  21. throws OASClientException, OASServerException;
  22. /**
  23. * 根据具体的UploadId上传文件。
  24. * 要配合 {@link initiateMultipartUpload} 使用
  25. * @param vaultName 目标vault名称
  26. * @param file 需要上传的文件
  27. * @param uploadId 初始化完成的Multipart的UploadId
  28. * @return 上传结果对象
  29. * @throws OASClientException
  30. * @throws OASServerException
  31. */
  32. public UploadResult uploadWithUploadId(String vaultName, File file, String uploadId)
  33. throws OASClientException, OASServerException;

示例代码:

  1. File file = new File("[pathToYourFile]");
  2. String vaultName = "[yourVaultName]";
  3. //获得uploadId
  4. //文件大小必须大于100MB,否则会抛异常提示用普通上传接口进行上传
  5. String uploadId = archiveManager.initiateMultipartUpload(vaultName, file, "Hello OAS!");
  6. //如果是已有的uploadId,直接使用之前获取过的uploadId
  7. //String uploadId = "[uploadIdYouAlreadyHave]";
  8. System.out.println("Get uploadId=" + uploadId);
  9. UploadResult uploadResult = archiveManager.uploadWithUploadId(vaultName, file, uploadId);
  10. System.out.println("Archive ID=" + uploadResult.getArchiveId());

使用已有的uploadId进行再次上传时,支持该任务的续传。例如,当一个Multipart任务在上传过程中被中止,这时,一些part已上传到OAS,一些part未完成。只要文件内容没有变化,根据保存下来的uploadId,可以继续上传这个文件剩余的part,已上传完毕的part不会重复上传。

如果开启了logger功能(如何配置logger请参考 《OAS Java SDK低级接口文档》),在日志中会看到以下信息:

  1. ....
  2. Range 33554432-67108863 got from OAS server, contentEtag=BEC7D9E8EC48FFD9C3859C10B64B4EDF, treeEtag=8DA41EA468F5613080A3D14857EFEFFE
  3. Range 33554432-67108863 has uploaded, contentEtag=BEC7D9E8EC48FFD9C3859C10B64B4EDF, treeEtag=8DA41EA468F5613080A3D14857EFEFFE
  4. Range 33554432-67108863 is the same as remote,ignore it. md5=BEC7D9E8EC48FFD9C3859C10B64B4EDF,etagTree=8DA41EA468F5613080A3D14857EFEFFE
  5. ....

只有当这个part的md5和etagTree的校验信息一致时,SDK才会忽略它的上传动作,否则,这个part会被重传。日志中会出现

  1. ....
  2. Range 33554432-67108863 local Etag data is different from remote. It will be uploaded again!
  3. ....

下载

在OAS服务协议中,下载是通过提交任务(Job)的形式存在的,按业务类型分为三类,分别是:

  1. 提交下载Archive任务
  2. 提交下载Inventory任务
  3. 下载Job输出

用户需要提交Job来获得他需要的数据,一个Job从创建到完成需要经历三步骤:

  1. 用户 通过接口提交相应类型的Job;
  2. OAS 接收到Job并安排其执行;
  3. 用户 将已完成Job的输出内容下载到本地。

:Job在OAS服务端是异步执行的,一个Job从提交到执行完毕这个过程一般耗时在几分钟到四小时之间。所以,所有下载类接口都是 异步接口 即全部以 Async 结尾。更多关于Job的信息,参考《OAS API文档 4.4 Job 操作》。

提交下载Archive Job

接口定义如下:

  1. /**
  2. * 提交请求下载archive任务请求
  3. * @param vaultName 目标vault名称
  4. * @param archiveId 需下载的archiveId
  5. * @return 返回Job信息跟踪器,可用来获取Job信息,如jobId,eTag校验信息
  6. * @throws OASClientException
  7. * @throws OASServerException
  8. */
  9. public JobMonitor downloadAsync(String vaultName, String archiveId)
  10. throws OASClientException, OASServerException;
  11. /**
  12. * 提交请求下载archive任务请求
  13. * @param vaultName 目标vault名称
  14. * @param archiveId 需下载的archiveId
  15. * @param description 备注
  16. * @return 返回Job信息跟踪器,可用来获取Job信息,如jobId,eTag校验信息
  17. * @throws OASClientException
  18. * @throws OASServerException
  19. */
  20. public JobMonitor downloadAsync(String vaultName, String archiveId, String description)
  21. throws OASClientException, OASServerException;
  22. /**
  23. * 提交请求下载archive任务请求
  24. * @param vaultName 目标vault名称
  25. * @param archiveId 需下载的archiveId
  26. * @param range 指定要下载的范围
  27. * @return 返回Job信息跟踪器,可用来获取Job信息,如jobId,eTag校验信息
  28. * @throws OASClientException
  29. * @throws OASServerException
  30. */
  31. public JobMonitor downloadWithRangeAsync(String vaultName, String archiveId, Range range)
  32. throws OASClientException, OASServerException;
  33. /**
  34. * 提交请求下载archive任务请求
  35. * @param vaultName 目标vault名称
  36. * @param archiveId 需下载的archiveId
  37. * @param range 指定要下载的范围
  38. * @param description 备注
  39. * @return 返回Job信息跟踪器,可用来获取Job信息,如jobId,eTag校验信息
  40. * @throws OASClientException
  41. * @throws OASServerException
  42. */
  43. public JobMonitor downloadWithRangeAsync(
  44. String vaultName, String archiveId, Range range, String description)
  45. throws OASClientException, OASServerException;

示例代码:

  1. JobMonitor jobMonitor = archiveManager.downloadAsync(
  2. "[yourVaultName]", "[yourArchiveId]");
  3. // JobMonitor提供的阻塞等待方法,直到Job状态完结
  4. // 实际场景中,不建议如此使用,因为Job的执行时间在几分钟到4小时不等
  5. // 长时间阻塞程序不是明智的做法
  6. jobMonitor.waitUntilFinished();
  7. System.out.println("Job has been comitted successfully.");
  8. System.out.println("Your JobId=" + jobMonitor.getJobId());

关于JobMonitor的具体使用方法,请阅读本文档 下载 章节的最后一部分 JobMonitor类使用讲解

提交Inventory任务

根据给定的Vault的名称, 提交Iventory任务后,OAS将准备好该Vault所包含文件的最后一次扫描信息,待Job执行完毕,可以将Vault的文件信息下载到本地。接口定义:

  1. /**
  2. * 根据vault名称获得vault的目录信息
  3. * @param vaultName 目标vault名称
  4. * @return
  5. */
  6. public JobMonitor downloadInventoryAsync(String vaultName)
  7. throws OASClientException, OASServerException;
  8. /**
  9. * 根据vault名称获得vault的目录信息
  10. * @param vaultName 目标vault名称
  11. * @param description 备注
  12. * @return
  13. * @throws OASClientException
  14. * @throws OASServerException
  15. */
  16. public JobMonitor downloadInventoryAsync(
  17. String vaultName, String description)
  18. throws OASClientException, OASServerException;

下载Job输出

根据给定的 Vault名称 和 JobID,下载Job的结果至本地文件。接口定义:

  1. /**
  2. * 下载Job输出到文件,只有当Job的状态是Succeeded或Failed(到达终结状态)时,才能执行此操作
  3. * @param vaultName 目标vault名称
  4. * @param jobId 要下载的jobId
  5. * @param file 保存的目标文件
  6. * @return 保存的目标文件的句柄对象
  7. * @throws OASClientException
  8. * @throws OASServerException
  9. */
  10. public File downloadJobOutput(String vaultName, String jobId, File file)
  11. throws OASClientException, OASServerException;
  12. /**
  13. * 下载Job输出到文件,只有当Job的状态是Succeeded或Failed(到达终结状态)时,才能执行此操作
  14. * @param vaultName 目标vault名称
  15. * @param jobId 要下载的jobId
  16. * @param file 保存的目标文件
  17. * @return 异步任务传输对象,可获得传输信息
  18. * @throws OASClientException
  19. * @throws OASServerException
  20. */
  21. public BaseTransfer<File> downloadJobOutputAsync(
  22. String vaultName, String jobId, File file)
  23. throws OASClientException, OASServerException;

JobMonitor类使用讲解

所有的下载动作,都是通过提交Job、下载Job输出的步骤完成。JobMonitor类是OAS JAVA SDK封装好,供用户跟踪Job信息的类,下面对JobMonitor类具体使用进行介绍。

  • waitUntilFinished()方法: 功能:阻塞住程序,每个1分钟请求OAS服务更新JobMonitor中Job的状态,直到Job的状态为 成功 或者 失败,取消阻塞,例如下面的代码,虽然这样使用是==不推荐==的:

    1. // JobMonitor提供的阻塞等待方法,直到Job状态完结
    2. // 注意,本方法不建议用户使用,因为一个Job从提交到完成,一般需要几分钟到4个小时不等
    3. // 长期阻塞程序,不是一个明智的选择
    4. // 这里的使用仅仅起到示例作用
    5. jobMonitor.waitUntilFinished();
    6. System.out.println("Job has ended.");
    7. System.out.println("JobId=" + jobMonitor.getJobId() + ", JobStatus="
    8. + jobMonitor.getJobStatus() + ", TreeEtag="
    9. + jobMonitor.getDescriptor().getTreeEtag());
  • checkJobFinishedWithRefresh()方法: 功能:向OAS服务发送一个请求,获取Job的最新状态,并判断最新状态是否为 成功、失败 中的一个,如果是,返回ture,否则返回false,示例代码如下,由于也会长期阻塞程序,这种用法也是 不推荐 的;

    1. while (true) {
    2. if (jobMonitor.checkJobFinishedWithRefresh()) {
    3. System.out.println("Job has ended.");
    4. System.out.println("JobId=" +
    5. jobMonitor.getJobId() + ", JobStatus="
    6. + jobMonitor.getJobStatus() + ", TreeEtag="
    7. + jobMonitor.getDescriptor().getTreeEtag());
    8. break;
    9. } else {
    10. try {
    11. Thread.sleep(1000);
    12. } catch (InterruptedException e) {
    13. logger.error("ERROR!", e);
    14. }
    15. }
    16. }
  • 推荐的JobMonitor的使用方法: 当使用ArchiveManager提交了Job后,可以从接口返回的JobMonitor中实时获取到本次任务的jobId,同样,ArchiveManager也提供了接口,根据jobId和vaultName实例化JobMonitor的方法:

    1. /**
    2. * 实例化JobMonitor
    3. * @param vaultName 目标vault名称
    4. * @param jobId 要实例化的jobId
    5. * @return
    6. * @throws OASClientException
    7. * @throws OASServerException
    8. */
    9. public JobMonitor getJobMonitor(String vaultName, String jobId)
    10. throws OASClientException, OASServerException;

    JobMonitor的实例化可以在用户程序的任何地方,随后用checkJobFinishedWithRefresh()等方法来检查Job的状态是否扭转,几个推荐的使用场景:

    1. 定时执行的任务中 (例如:可以每个小时扫描上一小时提交的Job的状态,再对Job输出进行下载);
    2. 某些业务事件被触发后(例如:业务中依赖这次Job输出的内容,否则该业务事件就无法执行);
    3. 用户触发。
  • 其他getter方法: 该类中有很多get方法,可以获得JobId(getJobId()方法)、JobStatus(getJobStatus()方法)等信息,但是这些方法获得的仅仅是本地的缓存,有可能和OAS服务端的信息不一致,如果需要手动从OAS服务端获取最新信息,可以执行 refreshJobDescriptorFromRemote()方法来实现。

异步接口中间过程的监听

异步接口与同步接口不同的是方法的返回值,一般来说,返回的对象是BaseTransfer,用户可通过ProgressListener监听进度,SpeedListener监听速度,通过start开始任务,stop停止任务,而waitUntilFinished将会阻塞直至任务完成,getResult可获取上传或下载结果。具体使用请参考本节的示例。

ProgressListenerSpeedListenerJobStatusListener分别为进度、速度、任务状态监听器,各个监听器的每个接口含义见下文的例子,而ProgressListenerAdapterSpeedListenerAdapterJobStatusListenerAdapter分别实现了以上接口,出错时默认会自动重试3次。特别注意的是,监听器部分接口的调用是在IO线程中,在监听器中执行费时的操作将有可能导致网络连接出错甚至中断。

以上传为例

  1. ServiceCredentials credentials = new ServiceCredentials(
  2. DemoConstants.ACCESS_ID,
  3. DemoConstants.ACCESS_KEY);
  4. // 通过工厂类获得archiveManager接口
  5. ArchiveManager archiveManager = OASFactory.archiveManagerFactory(credentials);
  6. File file = new File("[pathToYourFile]");
  7. final BaseTransfer<UploadResult> bt = archiveManager.uploadAsync(
  8. "[yourVaultName]", file);
  9. //设置最大并发数,默认为3,最大为10
  10. bt.setNumConcurrence(5);
  11. bt.addProgressListener(new ProgressListener() {
  12. @Override
  13. public void onStart(String id) {
  14. // 任务开始时调用,其中id为Multipart Upload任务ID,对于一般上传任务id为空
  15. System.out.println("Start! Upload ID: " + id);
  16. }
  17. @Override
  18. public boolean onError(Range range, Throwable t) {
  19. // 出错时调用,range是出错的字节范围,t是相应的错误
  20. // 当返回true时,BaseTransfer会进行重试,false则放弃
  21. System.out.println("ERROR!!!");
  22. return false;
  23. }
  24. @Override
  25. public void onCompleted() {
  26. // 任务完成时调用
  27. System.out.println("Upload complete");
  28. }
  29. @Override
  30. public void onProgressed(long current, long total) {
  31. // 上传进度,total为文件字节大小,current为当前已上传字节数
  32. System.out.println("Progress: " + current + " / " + total);
  33. }
  34. });
  35. bt.start();
  36. final Timer timer = new Timer();
  37. timer.scheduleAtFixedRate(new TimerTask() {
  38. @Override
  39. public void run() {
  40. System.out.println("Running time: " + bt.getRunningTime() + " seconds");
  41. System.out.println("Completed size: " + bt.getSizeCompleted() + " bytes");
  42. System.out.println("Total size: " + bt.getSizeTotal() + " bytes");
  43. System.out.println("Average speed: " + bt.getAverageSpeedInBytesPerSecond()
  44. + " B/s");
  45. if (bt.isComplete()) {
  46. timer.cancel();
  47. synchronized (bt) {
  48. bt.notify();
  49. }
  50. }
  51. }
  52. }, 0, 1000);
  53. synchronized (bt) {
  54. try {
  55. bt.wait();
  56. } catch (InterruptedException e) {
  57. logger.error("", e);
  58. }
  59. }
  60. // 任务结束
  61. System.out.println("=============================");
  62. System.out.println("Running time: " + bt.getRunningTime() + " seconds");
  63. System.out.println("Completed size: " + bt.getSizeCompleted() + " bytes");
  64. System.out.println("Total size: " + bt.getSizeTotal() + " bytes");
  65. System.out.println("Average speed: " + bt.getAverageSpeedInBytesPerSecond() + " B/s");
  66. UploadResult uploadResult = bt.getResult();
  67. System.out.println("Archive ID: " + uploadResult.getArchiveId());
  68. System.out.println("ContentEtag: " + uploadResult.getContentEtag());

异常

根据出错原因的不同,SDK把异常分为两种不同类型,分别为OAServerErrorOASClientError

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低级接口文档》