阿里雲團隊努力不懈,力求將最新的技術內容更快地以您最熟悉的語言呈現。本文由簡體中文內容自動轉碼而成,過程無人工干預。阿里雲不保證此自動轉碼的準確性、完整性及時效性。因轉碼造成的任何內容錯誤及因此可能帶來的損失,阿里雲概不負責,敬請見諒。本文内容請以簡體中文版本為準。
全部產品
Search
文件中心

分區上傳

更新時間: Oct 19, 2018

分區上傳(Multipart Upload)分為以下三個步驟:

  1. 初始化一個分區上傳事件。
    調用ossClient.initiateMultipartUpload方法返回OSS建立的全域唯一的uploadId。

  2. 上傳分區。
    調用ossClient.uploadPart方法上傳分區資料。需要注意:

    • 對於同一個uploadId,分區號(partNumber)標識了該分區在整個檔案內的相對位置。如果使用同一個分區號上傳了新的資料,那麼OSS上這個分區已有的資料將會被覆蓋。
    • OSS將收到的分區資料的MD5值放在ETag頭內返回給使用者。
    • SDK自動化佈建Content-MD5。OSS計算上傳資料的MD5值,並與SDK計算的MD5值比較,如果不一致則返回InvalidDigest錯誤碼。
  3. 完成分區上傳。
    所有分區上傳完成後,調用ossClient.completeMultipartUpload方法將所有分區合并成完整的檔案。

以下通過一個完整的樣本對分區上傳的流程進行逐步解析:

  1. // Endpoint以杭州為例,其它Region請按實際情況填寫。
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. String bucketName = "<yourBucketName>";
  7. String objectName = "<yourObjectName>";
  8. // 建立OSSClient執行個體。
  9. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  10. /* 步驟1:初始化一個分區上傳事件。
  11. */
  12. InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);
  13. InitiateMultipartUploadResult result = ossClient.initiateMultipartUpload(request);
  14. // 返回uploadId,它是分區上傳事件的唯一標識,您可以根據這個ID來發起相關的操作,如取消分區上傳、查詢分區上傳等。
  15. String uploadId = result.getUploadId();
  16. /* 步驟2:上傳分區。
  17. */
  18. // partETags是PartETag的集合。PartETag由分區的ETag和分區號組成。
  19. List<PartETag> partETags = new ArrayList<PartETag>();
  20. // 計算檔案有多少個分區。
  21. final long partSize = 1 * 1024 * 1024L; // 1MB
  22. final File sampleFile = new File("<localFile>");
  23. long fileLength = sampleFile.length();
  24. int partCount = (int) (fileLength / partSize);
  25. if (fileLength % partSize != 0) {
  26. partCount++;
  27. }
  28. // 遍曆分區上傳。
  29. for (int i = 0; i < partCount; i++) {
  30. long startPos = i * partSize;
  31. long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
  32. InputStream instream = new FileInputStream(sampleFile);
  33. // 跳過已經上傳的分區。
  34. instream.skip(startPos);
  35. UploadPartRequest uploadPartRequest = new UploadPartRequest();
  36. uploadPartRequest.setBucketName(bucketName);
  37. uploadPartRequest.setKey(objectName);
  38. uploadPartRequest.setUploadId(uploadId);
  39. uploadPartRequest.setInputStream(instream);
  40. // 設定分區大小。除了最後一個分區沒有大小限制,其他的分區最小為100KB。
  41. uploadPartRequest.setPartSize(curPartSize);
  42. // 設定分區號。每一個上傳的分區都有一個分區號,取值範圍是1~10000,如果超出這個範圍,OSS將返回InvalidArgument的錯誤碼。
  43. uploadPartRequest.setPartNumber( i + 1);
  44. // 每個分區不需要按順序上傳,甚至可以在不同用戶端上傳,OSS會按照分區號排序組成完整的檔案。
  45. UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
  46. // 每次上傳分區之後,OSS的返回結果會包含一個PartETag。PartETag將被保存到partETags中。
  47. partETags.add(uploadPartResult.getPartETag());
  48. }
  49. /* 步驟3:完成分區上傳。
  50. */
  51. // 排序。partETags必須按分區號升序排列。
  52. Collections.sort(partETags, new Comparator<PartETag>() {
  53. public int compare(PartETag p1, PartETag p2) {
  54. return p1.getPartNumber() - p2.getPartNumber();
  55. }
  56. });
  57. // 在執行該操作時,需要提供所有有效partETags。OSS收到提交的partETags後,會逐一驗證每個分區的有效性。當所有的資料分區驗證通過後,OSS將把這些分區組合成一個完整的檔案。
  58. CompleteMultipartUploadRequest completeMultipartUploadRequest =
  59. new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);
  60. ossClient.completeMultipartUpload(completeMultipartUploadRequest);
  61. // 關閉OSSClient。
  62. ossClient.shutdown();

分區上傳的完整代碼請參見GitHub

取消分區上傳事件

您可以調用ossClient.abortMultipartUpload方法來取消分區上傳事件。當一個分區上傳事件被取消後,無法再使用這個uploadId做任何操作,已經上傳的分區資料會被刪除。

以下代碼用於取消分區上傳事件:

  1. // Endpoint以杭州為例,其它Region請按實際情況填寫。
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. // 建立OSSClient執行個體。
  7. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  8. // 取消分區上傳,其中uploadId來自於InitiateMultipartUpload。
  9. AbortMultipartUploadRequest abortMultipartUploadRequest =
  10. new AbortMultipartUploadRequest("<yourBucketName>", "<yourObjectName>", "<uploadId>");
  11. ossClient.abortMultipartUpload(abortMultipartUploadRequest);
  12. // 關閉OSSClient。
  13. ossClient.shutdown();

列舉已上傳的分區

調用ossClient.listParts方法列舉出指定uploadId下所有已經上傳成功的分區。

簡單列舉已上傳的分區

以下代碼用於簡單列舉已上傳的分區:

  1. // Endpoint以杭州為例,其它Region請按實際情況填寫。
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. // 建立OSSClient執行個體。
  7. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  8. // 列舉已上傳的分區,其中uploadId來自於InitiateMultipartUpload返回的結果。
  9. ListPartsRequest listPartsRequest = new ListPartsRequest("<yourBucketName>", "<yourObjectName>", "<uploadId>");
  10. // 設定uploadId。
  11. //listPartsRequest.setUploadId(uploadId);
  12. // 設定分頁時每一頁中分區數量為100個。預設列舉1000個分區。
  13. listPartsRequest.setMaxParts(100);
  14. // 指定List的起始位置。只有分區號大於該參數值的分區會被列出。
  15. listPartsRequest.setPartNumberMarker(2);
  16. PartListing partListing = ossClient.listParts(listPartsRequest);
  17. for (PartSummary part : partListing.getParts()) {
  18. // 獲取分區號。
  19. part.getPartNumber();
  20. // 獲取分區資料大小。
  21. part.getSize();
  22. // 獲取分區的ETag。
  23. part.getETag();
  24. // 獲取分區的最後修改時間。
  25. part.getLastModified();
  26. }
  27. // 關閉OSSClient。
  28. ossClient.shutdown();

列舉所有已上傳的分區

預設情況下,listParts只能一次列舉1000個分區。當分區數量大於1000時,請使用以下代碼列舉所有已上傳的分區。

  1. // Endpoint以杭州為例,其它Region請按實際情況填寫。
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. // 建立OSSClient執行個體。
  7. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  8. // 列舉所有已上傳的分區。
  9. PartListing partListing;
  10. ListPartsRequest listPartsRequest = new ListPartsRequest("<yourBucketName>", "<yourObjectName>", "<uploadId>");
  11. do {
  12. partListing = ossClient.listParts(listPartsRequest);
  13. for (PartSummary part : partListing.getParts()) {
  14. // 獲取分區號。
  15. part.getPartNumber();
  16. // 獲取分區資料大小。
  17. part.getSize();
  18. // 獲取分區的ETag。
  19. part.getETag();
  20. // 獲取分區的最後修改時間。
  21. part.getLastModified();
  22. }
  23. // 指定List的起始位置,只有分區號大於該參數值的分區會被列出。
  24. listPartsRequest.setPartNumberMarker(partListing.getNextPartNumberMarker());
  25. } while (partListing.isTruncated());
  26. // 關閉OSSClient。
  27. ossClient.shutdown()

分頁列舉所有已上傳的分區

以下代碼用於指定每頁分區的數量,分頁列舉所有分區。

  1. // Endpoint以杭州為例,其它Region請按實際情況填寫。
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. // 建立OSSClient執行個體。
  7. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  8. // 分頁列舉已上傳的分區。
  9. PartListing partListing;
  10. ListPartsRequest listPartsRequest = new ListPartsRequest("<yourBucketName>", "<yourObjectName>", "<uploadId>");
  11. // 設定分頁時每一頁100個分區。
  12. listPartsRequest.setMaxParts(100);
  13. do {
  14. partListing = ossClient.listParts(listPartsRequest);
  15. for (PartSummary part : partListing.getParts()) {
  16. // 獲取分區號。
  17. part.getPartNumber();
  18. // 獲取分區資料大小。
  19. part.getSize();
  20. // 獲取分區的ETag。
  21. part.getETag();
  22. // 獲取分區的最後修改時間。
  23. part.getLastModified();
  24. }
  25. listPartsRequest.setPartNumberMarker(partListing.getNextPartNumberMarker());
  26. } while (partListing.isTruncated());
  27. // 關閉OSSClient。
  28. ossClient.shutdown();

列舉分區上傳事件

調用ossClient.listMultipartUploads方法列舉出所有執行中的分區上傳事件,即已初始化但尚未完成或已取消的分區上傳事件。可設定的參數如下:

參數 作用 如何設定
prefix 限定返回的檔案名稱必須以指定的prefix作為首碼。注意使用prefix查詢時,返回的檔案名稱中仍會包含prefix。 ListMultipartUploadsRequest.setPrefix(String prefix)
delimiter 用於對檔案名稱進行分組的一個字元。所有名稱包含指定的首碼且第一次出現delimiter字元之間的檔案作為一組元素。 ListMultipartUploadsRequest.setDelimiter(String delimiter)
maxUploads 限定此次返回分區上傳事件的最大數目,預設值和最大值均為1000。 ListMultipartUploadsRequest.setMaxUploads(Integer maxUploads)
keyMarker 所有檔案名稱的字母序大於keyMarker參數值的分區上傳事件。可以與uploadIdMarker參數一同使用來指定返回結果的起始位置。 ListMultipartUploadsRequest.setKeyMarker(String keyMarker)
uploadIdMarker 與keyMarker參數一同使用來指定返回結果的起始位置。 如果未設定keyMarker參數,則此參數無效。如果設定了keyMarker參數,則查詢結果中包含:
- 名稱的字母序大於keyMarker參數值的所有檔案。
- 檔案名稱等於keyMarker參數值且uploadId比uploadIdMarker參數值大的所有分區上傳事件。
ListMultipartUploadsRequest.setUploadIdMarker(String uploadIdMarker)

簡單列舉分區上傳事件

以下代碼用於列舉分區上傳事件:

  1. // Endpoint以杭州為例,其它Region請按實際情況填寫。
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. String bucketName = "<yourBucketName>";
  7. // 建立OSSClient執行個體。
  8. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  9. // 列舉分區上傳事件。預設列舉1000個分區。
  10. ListMultipartUploadsRequest listMultipartUploadsRequest = new ListMultipartUploadsRequest(bucketName);
  11. MultipartUploadListing multipartUploadListing = ossClient.listMultipartUploads(listMultipartUploadsRequest);
  12. for (MultipartUpload multipartUpload : multipartUploadListing.getMultipartUploads()) {
  13. // 獲取uploadId。
  14. multipartUpload.getUploadId();
  15. // 獲取Key。
  16. multipartUpload.getKey();
  17. // 獲取分區上傳的初始化時間。
  18. multipartUpload.getInitiated();
  19. }
  20. // 關閉OSSClient。
  21. ossClient.shutdown();

返回結果中isTruncated為false,返回nextKeyMarker和nextUploadIdMarker作為下次讀取的起點。如果沒有一次性獲取所有的上傳事件,可以採用分頁列舉的方式。

列舉全部分區上傳事件

預設情況下,listMultipartUploads 只能一次列舉1000個分區。當分區數量大於1000時,請使用以下代碼列舉全部分區上傳事件。

  1. // Endpoint以杭州為例,其它Region請按實際情況填寫。
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. String bucketName = "<yourBucketName>";
  7. // 建立OSSClient執行個體。
  8. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  9. // 列舉分區上傳事件。
  10. MultipartUploadListing multipartUploadListing;
  11. ListMultipartUploadsRequest listMultipartUploadsRequest = new ListMultipartUploadsRequest(bucketName);
  12. do {
  13. multipartUploadListing = ossClient.listMultipartUploads(listMultipartUploadsRequest);
  14. for (MultipartUpload multipartUpload : multipartUploadListing.getMultipartUploads()) {
  15. // 獲取uploadId。
  16. multipartUpload.getUploadId();
  17. // 獲取檔案名稱。
  18. multipartUpload.getKey();
  19. // 獲取分區上傳的初始化時間。
  20. multipartUpload.getInitiated();
  21. }
  22. listMultipartUploadsRequest.setKeyMarker(multipartUploadListing.getNextKeyMarker());
  23. listMultipartUploadsRequest.setUploadIdMarker(multipartUploadListing.getNextUploadIdMarker());
  24. } while (multipartUploadListing.isTruncated());
  25. // 關閉OSSClient。
  26. ossClient.shutdown();

分頁列舉全部上傳事件

以下代碼用於分頁列舉所有上傳事件:

  1. // Endpoint以杭州為例,其它Region請按實際情況填寫。
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. String bucketName = "<yourBucketName>";
  7. // 建立OSSClient執行個體。
  8. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  9. // 列舉分區上傳事件。
  10. MultipartUploadListing multipartUploadListing;
  11. ListMultipartUploadsRequest listMultipartUploadsRequest = new ListMultipartUploadsRequest(bucketName);
  12. // 設定每頁列舉的分區上傳事件數目目。
  13. listMultipartUploadsRequest.setMaxUploads(50);
  14. do {
  15. multipartUploadListing = ossClient.listMultipartUploads(listMultipartUploadsRequest);
  16. for (MultipartUpload multipartUpload : multipartUploadListing.getMultipartUploads()) {
  17. // 獲取uploadId。
  18. multipartUpload.getUploadId();
  19. // 獲取Key。
  20. multipartUpload.getKey();
  21. // 獲取分區上傳的初始化時間。
  22. multipartUpload.getInitiated();
  23. }
  24. listMultipartUploadsRequest.setKeyMarker(multipartUploadListing.getNextKeyMarker());
  25. listMultipartUploadsRequest.setUploadIdMarker(multipartUploadListing.getNextUploadIdMarker());
  26. } while (multipartUploadListing.isTruncated());
  27. // 關閉OSSClient。
  28. ossClient.shutdown();