閱讀212 返回首頁    go 微信


下載文件__Java-SDK_SDK 參考_對象存儲 OSS-阿裏雲

OSS Java SDK提供了豐富的文件下載接口,用戶可以通過以下方式從OSS中下載文件:

  • 流式下載
  • 下載到本地文件
  • 斷點續傳下載
  • 範圍下載

流式下載

在進行大文件下載時,往往不希望一次性處理全部內容,而是希望流式地處理,一次處理一部分內容。

提示:

  • 流式下載的完整代碼請參考:GitHub
  1. // endpoint以杭州為例,其它region請按實際情況填寫
  2. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
  3. // accessKey請登錄https://ak-console.aliyun.com/#/查看
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. String bucketName = "<yourBucketName>";
  7. // 創建OSSClient實例
  8. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  9. OSSObject ossObject = ossClient.getObject(bucketName, "yourKey");
  10. // 讀Object內容
  11. System.out.println("Object content:");
  12. BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
  13. while (true) {
  14. String line = reader.readLine();
  15. if (line == null) break;
  16. System.out.println("n" + line);
  17. }
  18. reader.close();
  19. // 關閉client
  20. ossClient.shutdown();

提示:

  • OSSObject實例包含文件所在的存儲空間(Bucket)、文件的名稱、Object Metadata以及一個輸入流;
  • 通過操作輸入流將文件的內容讀取到文件或者內存中。而Object Metadata包含ETag、HTTP Header及自定義的元信息;
  • OSSClient.getObject獲取的流一定要顯示close,否則會造成資源泄露;
    1. OSSObject ossObject = ossClient.getObject(bucketName, key);
    2. ossObject.getObjectContent().close();
  • 假如需要從OSS流式讀取64KB的數據,請使用如下的方式多次讀取,直到讀取64KB或者文件結束:
    1. byte[] buf = new byte[1024];
    2. InputStream in = ossObject.getObjectContent();
    3. for (int n = 0; n != -1; ) {
    4. n = in.read(buf, 0, buf.length);
    5. }
    6. in.close();
    而不是如下的形式:
    1. byte[] buf = new byte[64 * 1024];
    2. InputStream in = ossObject.getObjectContent();
    3. in.read(buf, 0, buf.length);
    4. in.close();
    原因是,流式讀取一次不一定能讀到全部數據,詳細說明請參考 InputStream.read

下載到本地文件

把Object的內容下載到指定的本地文件中。如果指定的本地文件不存在則會新建。

  1. // endpoint以杭州為例,其它region請按實際情況填寫
  2. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
  3. // accessKey請登錄https://ak-console.aliyun.com/#/查看
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. String bucketName = "<yourBucketName>";
  7. // 創建OSSClient實例
  8. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  9. // 下載object到文件
  10. ossClient.getObject(new GetObjectRequest(bucketName, "<yourKey>"), new File("<yourLocalFile>"));
  11. // 關閉client
  12. ossClient.shutdown();

範圍下載

如果OSS文件較大,並且隻需要其中一部分數據,可以使用範圍下載,下載指定範圍的數據。如果指定的下載範圍是0 - 100,則返回第0到第100個字節的數據,包括第100個,共101字節的數據,即[0, 100]。如果指定的範圍無效,則傳送整個文件。

  1. // endpoint以杭州為例,其它region請按實際情況填寫
  2. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
  3. // accessKey請登錄https://ak-console.aliyun.com/#/查看
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. String bucketName = "<yourBucketName>";
  7. // 創建OSSClient實例
  8. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  9. GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, "<yourKey>");
  10. // 獲取0~1000字節範圍內的數據,包括0和1000,共1001個字節的數據
  11. getObjectRequest.setRange(0, 1000);
  12. // 範圍下載
  13. OSSObject ossObject = ossClient.getObject(getObjectRequest);
  14. // 讀取數據
  15. byte[] buf = new byte[1024];
  16. InputStream in = ossObject.getObjectContent();
  17. for (int n = 0; n != -1; ) {
  18. n = in.read(buf, 0, buf.length);
  19. }
  20. // InputStream數據讀完成後,一定要close,否則會造成連接泄漏
  21. in.close();
  22. // 關閉client
  23. ossClient.shutdown();

提示:

  • 如果指定的Range無效(比如開始位置、結束位置為負數,大於文件大小),則會下載整個文件;
  • 假如需要從OSS流式讀取64KB的數據,請使用如下的方式多次讀取,直到讀取64KB或者文件結束:
    1. byte[] buf = new byte[1024];
    2. InputStream in = ossObject.getObjectContent();
    3. for (int n = 0; n != -1; ) {
    4. n = in.read(buf, 0, buf.length);
    5. }
    6. in.close();
    而不是如下的形式:
    1. byte[] buf = new byte[64 * 1024];
    2. InputStream in = ossObject.getObjectContent();
    3. in.read(buf, 0, buf.length);
    4. in.close();
    原因是,流式讀取一次不一定能讀到全部數據,詳細說明請參考 InputStream.read

斷點續傳下載

當下載大文件時,如果網絡不穩定或者程序崩潰了,則整個下載就失敗了。用戶不得不重頭再來,這樣做不僅浪費資源,在網絡不穩定的情況下,往往重試多次還是無法完成下載。通過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文件會被刪除。

  1. // endpoint以杭州為例,其它region請按實際情況填寫
  2. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
  3. // accessKey請登錄https://ak-console.aliyun.com/#/查看
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. String bucketName = "<yourBucketName>";
  7. // 創建OSSClient實例
  8. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  9. // 下載請求,10個任務並發下載,啟動斷點續傳
  10. DownloadFileRequest downloadFileRequest = new DownloadFileRequest("bucketName", "key");
  11. downloadFileRequest.setDownloadFile("downloadFile");
  12. downloadFileRequest.setTaskNum(10);
  13. downloadFileRequest.setEnableCheckpoint(true);
  14. // 下載文件
  15. DownloadFileResult downloadRes = ossClient.downloadFile(downloadFileRequest);
  16. // 下載成功時,會返回文件的元信息
  17. downloadRes.getObjectMetadata();
  18. // 關閉client
  19. 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。
  1. // endpoint以杭州為例,其它region請按實際情況填寫
  2. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
  3. // accessKey請登錄https://ak-console.aliyun.com/#/查看
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. String bucketName = "<yourBucketName>";
  7. // 創建OSSClient實例
  8. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  9. GetObjectRequest request = new GetObjectRequest(bucketName, "<yourKey>");
  10. request.setModifiedSinceConstraint(new Date());
  11. // 下載object到文件
  12. ossClient.getObject(request, new File("<yourLocalFile>"));
  13. // 關閉client
  14. ossClient.shutdown();

提示:

  • ETag的值可以通過OSSClient.getObjectMetadata獲取;
  • OSSClient.getObject,OSSClient.downloadFile都支持限定條件。

下載進度條

OSS Java sdk支持進度條功能,指示上傳/下載的進度。下麵的代碼以OSSClient.getObject為例,說明進度條功能的使用。

提示:

  • 下載進度條的完整代碼請參考:GitHub
  1. static class GetObjectProgressListener implements ProgressListener {
  2. private long bytesRead = 0;
  3. private long totalBytes = -1;
  4. private boolean succeed = false;
  5. @Override
  6. public void progressChanged(ProgressEvent progressEvent) {
  7. long bytes = progressEvent.getBytes();
  8. ProgressEventType eventType = progressEvent.getEventType();
  9. switch (eventType) {
  10. case TRANSFER_STARTED_EVENT:
  11. System.out.println("Start to download......");
  12. break;
  13. case RESPONSE_CONTENT_LENGTH_EVENT:
  14. this.totalBytes = bytes;
  15. System.out.println(this.totalBytes + " bytes in total will be downloaded to a local file");
  16. break;
  17. case RESPONSE_BYTE_TRANSFER_EVENT:
  18. this.bytesRead += bytes;
  19. if (this.totalBytes != -1) {
  20. int percent = (int)(this.bytesRead * 100.0 / this.totalBytes);
  21. System.out.println(bytes + " bytes have been read at this time, download progress: " +
  22. percent + "%(" + this.bytesRead + "/" + this.totalBytes + ")");
  23. } else {
  24. System.out.println(bytes + " bytes have been read at this time, download ratio: unknown" +
  25. "(" + this.bytesRead + "/...)");
  26. }
  27. break;
  28. case TRANSFER_COMPLETED_EVENT:
  29. this.succeed = true;
  30. System.out.println("Succeed to download, " + this.bytesRead + " bytes have been transferred in total");
  31. break;
  32. case TRANSFER_FAILED_EVENT:
  33. System.out.println("Failed to download, " + this.bytesRead + " bytes have been transferred");
  34. break;
  35. default:
  36. break;
  37. }
  38. }
  39. public boolean isSucceed() {
  40. return succeed;
  41. }
  42. }
  43. public static void main(String[] args) {
  44. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
  45. String accessKeyId = "<accessKeyId>";
  46. String accessKeySecret = "<accessKeySecret>";
  47. String bucketName = "<bucketName>";
  48. String key = "object-get-progress-sample";
  49. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  50. try {
  51. // 帶進度條的下載
  52. client.getObject(new GetObjectRequest(bucketName, key).
  53. <GetObjectRequest>withProgressListener(new GetObjectProgressListener()),
  54. new File("<yourLocalFile>"));
  55. } catch (Exception e) {
  56. e.printStackTrace();
  57. }
  58. ossClient.shutdown();
  59. }

提示:

  • putObject/getObject/uploadPart都支持進度條功能;
  • uploadFile/downloadFile不支持進度條功能。

最後更新:2016-11-23 16:04:10

  上一篇:go 管理Bucket__Java-SDK_SDK 參考_對象存儲 OSS-阿裏雲
  下一篇:go 管理文件__Java-SDK_SDK 參考_對象存儲 OSS-阿裏雲