OSS JAVA SDK

安裝OSS JAVA SDK

直接在Eclipse中使用JAR包

步驟以下:php

  • 在官方網站下載 Open Service Java SDK 。
  • 解壓文件。
  • 將解壓後文件夾中的文件: aliyun-openservice-<versionId>.jar 以及lib文件夾下的全部文件拷貝到你的工程文件夾中。
  • 在Eclipse右鍵工程 -> Properties -> Java Build Path -> Add JARs 。
  • 選擇你拷貝的全部JAR文件。

通過上面幾步以後,你就能夠在工程中使用OSS JAVA SDK了。html

在Maven工程中使用SDK

在Maven工程中使用JAVA SDK十分簡單,只要在在pom.xml文件中加入依賴就能夠了。java

在 dependencies 標籤內加入以下內容:python

<dependency>
    <groupId>com.aliyun.openservices</groupId> <artifactId>aliyun-openservices</artifactId> <version>1.0.10</version> </dependency> 

version爲版本號,隨着版本更新可能有變更。api

 

快速入門

在這一章裏,您將學到如何用OSS Java SDK完成一些基本的操做。瀏覽器

Step 1. 初始化一個OSSClient

OSSClient是與OSS服務交互的客戶端,SDK的OSS操做都是經過OSSClient完成的。服務器

下面代碼新建了一個OSSClient:網絡

import com.aliyun.openservices.oss.OSSClient; public class Sample { public static void main(String[] args) { String accessKeyId = "<key>"; String accessKeySecret = "<secret>"; // 初始化一個OSSClient OSSClient client = new OSSClient(accessKeyId, accessKeySecret); // 下面是一些調用代碼... ... } } 

在上面代碼中,變量 accessKeyId 與 accessKeySecret 是由系統分配給用戶的,稱爲ID對,用於標識用戶,爲訪問OSS作簽名驗證。eclipse

關於OSSClient的詳細介紹,參見 OSSClient 。maven

Step 2. 新建Bucket

Bucket是OSS上的命名空間,至關於數據的容器,能夠存儲若干數據實體(Object)。

你能夠按照下面的代碼新建一個Bucket:

public void createBucket(String bucketName) { // 初始化OSSClient OSSClient client = ...; // 新建一個Bucket client.createBucket(bucketName); } 

因爲Bucket的名字是全局惟一的,因此儘可能保證你的 bucketName 不與別人重複。

關於Bucket的命名規範,參見 Bucket命名規範

Step 3. 上傳Object

Object是OSS中最基本的數據單元,你能夠把它簡單地理解爲文件,用下面代碼能夠實現一個Object的上傳:

public void putObject(String bucketName, String key, String filePath) throws FileNotFoundException { // 初始化OSSClient OSSClient client = ...; // 獲取指定文件的輸入流 File file = new File(filePath); InputStream content = new FileInputStream(file); // 建立上傳Object的Metadata ObjectMetadata meta = new ObjectMetadata(); // 必須設置ContentLength meta.setContentLength(file.length()); // 上傳Object. PutObjectResult result = client.putObject(bucketName, key, content, meta); // 打印ETag System.out.println(result.getETag()); } 

Object經過InputStream的形式上傳到OSS中。在上面的例子裏咱們能夠看出,每上傳一個Object,都須要指定和Object關聯的ObjectMetadata。ObjectMetaData是用戶對該object的描述,由一系列name-value對組成;其中ContentLength是必須設置的,以便SDK能夠正確識別上傳Object的大小。

Put Object請求處理成功後,OSS會將收到文件的MD5值放在返回結果的ETag中。用戶能夠根據ETag檢驗上傳的文件與本地的是否一致。

關於Object的命名規範,參見 Object命名規範 。

關於上傳Object更詳細的信息,參見 上傳Object 。

Step 4. 列出全部Object

當你完成一系列上傳後,可能會須要查看在某個Bucket中有哪些Object,能夠經過下面的程序實現:

public void listObjects(String bucketName) { // 初始化OSSClient OSSClient client = ...; // 獲取指定bucket下的全部Object信息 ObjectListing listing = client.listObjects(bucketName); // 遍歷全部Object for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) { System.out.println(objectSummary.getKey()); } } 

listObjects方法會返回ObjectListing對象,ObjectListing對象包含了這次listObject請求的返回結果。其中咱們能夠經過ObjetListing中的getObjectSummaries方法獲取全部Object的描述信息(List<OSSObjectSummary>)。

Step 5. 獲取指定Object

你能夠參考下面的代碼簡單地實現一個Object的獲取:

public void getObject(String bucketName, String key) throws IOException { // 初始化OSSClient OSSClient client = ...; // 獲取Object,返回結果爲OSSObject對象 OSSObject object = client.getObject(bucketName, key); // 獲取Object的輸入流 InputStream objectContent = object.getObjectContent(); // 處理Object ... // 關閉流 objectContent.close(); } 

當調用OSSClient的getObject方法時,會返回一個OSSObject的對象,此對象包含了Object的各類信息。經過OSSObject的getObjectContent方法,還能夠獲取返回的Object的輸入流,你能夠讀取這個輸入流來對Object的內容進行操做;記得在用完以後關閉這個流。

 

OSSClient

OSSClient是OSS服務的Java客戶端,它爲調用者提供了一系列的方法,用於和OSS服務進行交互。

新建OSSClient

新建一個OSSClient很簡單,以下面代碼所示:

String key = "<key>"; String secret = "<secret>"; OSSClient client = new OSSClient(key, secret); 

上面的方式使用默認域名做爲OSS的服務地址,若是你想本身指定域名,能夠傳入endpoint參數來指定。

String key = "<key>"; String secret = "<secret>"; String endpoint = "http://oss.aliyuncs.com"; OSSClient client = new OSSClient(endpoint, accessKeyId, accessKeySecret); 

配置OSSClient

若是你想配置OSSClient的一些細節的參數,能夠在構造OSSClient的時候傳入ClientConfiguration對象。 ClientConfiguration是OSS服務的配置類,能夠爲客戶端配置代理,最大鏈接數等參數。

使用代理

下面一段代碼可使客戶端使用代理訪問OSS服務:

// 建立ClientConfiguration實例
ClientConfiguration conf = new ClientConfiguration(); // 配置代理爲本地8080端口 conf.setProxyHost("127.0.0.1"); conf.setProxyPort(8080); // 建立OSS客戶端 client = new OSSClient(endpoint, accessKeySecret, accessKeySecret, conf); 

上面代碼使得客戶端的全部操做都會使用127.0.0.1地址的8080端口作代理執行。

對於有用戶驗證的代理,能夠配置用戶名和密碼:

// 建立ClientConfiguration實例
ClientConfiguration conf = new ClientConfiguration(); // 配置代理爲本地8080端口 conf.setProxyHost("127.0.0.1"); conf.setProxyPort(8080); //設置用戶名和密碼 conf.setProxyUsername("username"); conf.setProxyPassword("password"); 

設置網絡參數

咱們能夠用ClientConfiguration設置一些網絡參數:

ClientConfiguration conf = new ClientConfiguration(); // 設置HTTP最大鏈接數爲10 conf.setMaxConnections(10); // 設置TCP鏈接超時爲5000毫秒 conf.setConnectionTimeout(5000); // 設置最大的重試次數爲3 conf.setMaxErrorRetry(3); // 設置Socket傳輸數據超時的時間爲2000毫秒 conf.setSocketTimeout(2000); 

ClientConfiguration全部參數

經過ClientConfiguration能指定的全部參數以下表所示:

參數 說明
UserAgent 用戶代理,指HTTP的User-Agent頭。默認爲」aliyun-sdk-java」
ProxyHost 代理服務器主機地址
ProxyPort 代理服務器端口
ProxyUsername 代理服務器驗證的用戶名
ProxyPassword 代理服務器驗證的密碼
ProxyDomain 訪問NTLM驗證的代理服務器的Windows域名
ProxyWorkstation NTLM代理服務器的Windows工做站名稱
MaxConnections 容許打開的最大HTTP鏈接數。默認爲50
SocketTimeout 經過打開的鏈接傳輸數據的超時時間(單位:毫秒)。默認爲50000毫秒
ConnectionTimeout 創建鏈接的超時時間(單位:毫秒)。默認爲50000毫秒
MaxErrorRetry 可重試的請求失敗後最大的重試次數。默認爲3次

 

Bucket

Bucket是OSS上的命名空間,也是計費、權限控制、日誌記錄等高級功能的管理實體;Bucket名稱在整個OSS服務中具備全局惟一性,且不能修改;存儲在OSS上的每一個Object必須都包含在某個Bucket中。一個應用,例如圖片分享網站,能夠對應一個或多個Bucket。一個用戶最多可建立10個Bucket,但每一個Bucket中存放的Object的數量和大小總和沒有限制,用戶不須要考慮數據的可擴展性。

命名規範

Bucket的命名有如下規範:

  • 只能包括小寫字母,數字,短橫線(-)
  • 必須以小寫字母或者數字開頭
  • 長度必須在3-63字節之間

新建Bucket

以下代碼能夠新建一個Bucket:

String bucketName = "my-bucket-name"; // 初始化OSSClient OSSClient client = ...; // 新建一個Bucket client.createBucket(bucketName); 

因爲Bucket的名字是全局惟一的,因此儘可能保證你的 bucketName 不與別人重複。

列出用戶全部的Bucket

下面代碼能夠列出用戶全部的Bucket:

// 獲取用戶的Bucket列表
List<Bucket> buckets = client.listBuckets(); // 遍歷Bucket for (Bucket bucket : buckets) { System.out.println(bucket.getName()); } 

判斷Bucket是否存在

有時候,咱們的需求只是判斷Bucket是否存在。則下面代碼能夠作到:

String bucketName = "your-bucket-name"; // 獲取Bucket的存在信息 boolean exists = client.doesBucketExist(bucketName); // 輸出結果 if (exists) { System.out.println("Bucket exists"); } else { System.out.println("Bucket not exists"); } 

刪除Bucket

下面代碼刪除了一個Bucket:

String bucketName = "your-bucket-name"; // 刪除Bucket client.deleteBucket(bucketName) 

須要注意的是,若是Bucket不爲空(Bucket中有Object),則Bucket沒法刪除,必須清空Bucket後才能成功刪除。

Bucket權限控制

Bucket的訪問權限

OSS提供Bucket級別的權限訪問控制,Bucket目前有三種訪問權限:public-read-write,public-read和private。它們的含義以下:

  • public-read-write: 任何人(包括匿名訪問)均可以對該bucket中的object進行上傳、下載和刪除操做;全部這些操做產生的費用由該bucket的建立者承擔,請慎用該權限。
  • public-read: 只有該bucket的建立者能夠對該bucket內的Object進行寫操做(包括上傳和刪除);任何人(包括匿名訪問)能夠對該bucket中的object進行讀操做。
  • private: 只有該bucket的建立者才能夠訪問此Bukcet。其餘人禁止對此Bucket作任何操做。

用戶新建立一個新Bucket時,若是不指定Bucket權限,OSS會自動爲該Bucket設置private權限。對於一個已經存在的Bucket,只有它的建立者能夠經過OSS的所提供的接口修改其訪問權限。

修改Bucket的訪問權限

下面代碼將Bucket的權限設置爲了private。

String bucketName = "your-bucket-name"; client.setBucketAcl(bucketName, CannedAccessControlList.Private); 

CannedAccessControlList是枚舉類型,包含三個值: Private 、 PublicRead 、 PublicReadWrite ,它們分別對應相關權限。

 

Object

在OSS中,用戶操做的基本數據單元是Object。單個Object最大容許存儲5TB的數據。Object包含key、meta和data。其中,key是Object的名字;meta是用戶對該object的描述,由一系列name-value對組成;data是Object的數據。

命名規範

Object的命名規範以下:

  • 使用UTF-8編碼
  • 長度必須在1-1023字節之間
  • 不能以「/」或者「\」字符開頭
  • 不能含有「\r」或者「\n」的換行符

上傳Object

最簡單的上傳

以下代碼:

public void putObject(String bucketName, String key, String filePath) throws FileNotFoundException { // 初始化OSSClient OSSClient client = ...; // 獲取指定文件的輸入流 File file = new File(filePath); InputStream content = new FileInputStream(file); // 建立上傳Object的Metadata ObjectMetadata meta = new ObjectMetadata(); // 必須設置ContentLength meta.setContentLength(file.length()); // 上傳Object. PutObjectResult result = client.putObject(bucketName, key, content, meta); // 打印ETag System.out.println(result.getETag()); } 

Object經過InputStream的形式上傳到OSS中。在上面的例子裏咱們能夠看出,每上傳一個Object,都須要指定和Object關聯的ObjectMetadata。ObjectMetaData是用戶對該object的描述,由一系列name-value對組成;其中ContentLength是必須設置的,以便SDK能夠正確識別上傳Object的大小。

Put Object請求處理成功後,OSS會將收到文件的MD5值放在返回結果的ETag中。用戶能夠根據ETag檢驗上傳的文件與本地的是否一致。

設定Object的Http Header

OSS Java SDK本質上是調用後臺的HTTP接口,所以OSS服務容許用戶自定義Object的Http Header。下面代碼爲Object設置了過時時間:

// 初始化OSSClient
OSSClient client = ...; // 初始化上傳輸入流 InputStream content = ...; // 建立上傳Object的Metadata ObjectMetadata meta = new ObjectMetadata(); // 設置ContentLength爲1000 meta.setContentLength(1000); // 設置1小時後過時 Date expire = new Date(new Date().getTime() + 3600 * 1000); meta.setExpirationTime(expire); client.putObject(bucketName, key, content, meta); 

Java SDK支持的Http Header有四種,分別爲:Cache-Control 、 Content-Disposition 、Content-Encoding 、 Expires 。它們的相關介紹見 RFC2616 。

用戶自定義元數據

OSS支持用戶自定義元數據來對Object進行描述。好比:

// 設置自定義元數據name的值爲my-data
meta.addUserMetadata("name", "my-data"); // 上傳object client.putObject(bucketName, key, content, meta); 

在上面代碼中,用戶自定義了一個名字爲」name」,值爲」my-data」的元數據。當用戶下載此Object的時候,此元數據也能夠一併獲得。一個Object能夠有多個相似的參數,但全部的user meta總大小不能超過2k。

分塊上傳

OSS容許用戶將一個Object分紅多個請求上傳到後臺服務器中,關於分塊上傳的內容,咱們將在 Object的分塊上傳 這一章中作介紹。

列出Bucket中的Object

列出Object

public void listObjects(String bucketName) { // 初始化OSSClient OSSClient client = ...; // 獲取指定bucket下的全部Object信息 ObjectListing listing = client.listObjects(bucketName); // 遍歷全部Object for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) { System.out.println(objectSummary.getKey()); } } 

listObjects方法會返回 ObjectListing 對象,ObjectListing 對象包含了這次listObject請求的返回結果。其中咱們能夠經過 ObjetListing 中的 getObjectSummaries 方法獲取全部Object的描述信息(List<OSSObjectSummary>)。

Note

 

默認狀況下,若是Bucket中的Object數量大於100,則只會返回100個Object, 且返回結果中 IsTruncated 爲 false,並返回 NextMarker 做爲下此讀取的起點。若想增大返回Object數目,能夠修改 MaxKeys 參數,或者使用 Marker 參數分次讀取。

擴展參數

一般,咱們能夠經過設置ListObjectsRequest的參數來完成更強大的功能。好比:

// 構造ListObjectsRequest請求
ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName); // 設置參數 listObjectsRequest.setDelimiter("/"); listObjectsRequest.setMarker("123"); ... ObjectListing listing = client.listObjects(listObjectsRequest); 

上面代碼中咱們調用了 listObjects 的一個重載方法,經過傳入 ListObjectsRequest 來完成請求。經過 ListObjectsRequest 中的參數設置咱們能夠完成不少擴展的功能。下表列出了 ListObjectsRequest 中能夠設置的參數名稱和做用:

名稱 做用
Delimiter 是一個用於對Object名字進行分組的字符。全部名字包含指定的前綴且第一次出現Delimiter字符之間的object做爲一組元素: CommonPrefixes。
Marker 設定結果從Marker以後按字母排序的第一個開始返回。
MaxKeys 限定這次返回object的最大數,若是不設定,默認爲100,MaxKeys取值不能大於1000。
Prefix 限定返回的object key必須以Prefix做爲前綴。注意使用prefix查詢時,返回的key中仍會包含Prefix。

文件夾功能模擬

咱們能夠經過 Delimiter 和 Prefix 參數的配合模擬出文件夾功能。

Delimiter 和 Prefix 的組合效果是這樣的:若是把 Prefix 設爲某個文件夾名,就能夠羅列以此 Prefix 開頭的文件,即該文件夾下遞歸的全部的文件和子文件夾。若是再把 Delimiter 設置爲 「/」 時,返回值就只羅列該文件夾下的文件,該文件夾下的子文件名返回在 CommonPrefixes 部分,子文件夾下遞歸的文件和文件夾不被顯示.

假設Bucket中有4個文件: oss.jpg , fun/test.jpg , fun/movie/001.avi , fun/movie/007.avi ,咱們把 「/」 符號做爲文件夾的分隔符。

列出Bucket內全部文件

當咱們須要獲取Bucket下的全部文件時,能夠這樣寫:

// 構造ListObjectsRequest請求
ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName); // List Objects ObjectListing listing = client.listObjects(listObjectsRequest); // 遍歷全部Object System.out.println("Objects:"); for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) { System.out.println(objectSummary.getKey()); } // 遍歷全部CommonPrefix System.out.println("CommonPrefixs:"); for (String commonPrefix : listing.getCommonPrefixes()) { System.out.println(commonPrefix); } 

輸出:

Objects:
fun/movie/001.avi
fun/movie/007.avi
fun/test.jpg
oss.jpg

CommonPrefixs:

遞歸列出目錄下全部文件

咱們能夠經過設置 Prefix 參數來獲取某個目錄下全部的文件:

// 構造ListObjectsRequest請求
ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName); // 遞歸列出fun目錄下的全部文件 listObjectsRequest.setPrefix("fun/"); ObjectListing listing = client.listObjects(listObjectsRequest); // 遍歷全部Object System.out.println("Objects:"); for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) { System.out.println(objectSummary.getKey()); } // 遍歷全部CommonPrefix System.out.println("\nCommonPrefixs:"); for (String commonPrefix : listing.getCommonPrefixes()) { System.out.println(commonPrefix); } 

輸出:

Objects:
fun/movie/001.avi
fun/movie/007.avi
fun/test.jpg

CommonPrefixs:

列出目錄下的文件和子目錄

在 Prefix 和 Delimiter 結合的狀況下,能夠列出目錄下的文件和子目錄:

// 構造ListObjectsRequest請求
ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName); // "/" 爲文件夾的分隔符 listObjectsRequest.setDelimiter("/"); // 列出fun目錄下的全部文件和文件夾 listObjectsRequest.setPrefix("fun/"); ObjectListing listing = client.listObjects(listObjectsRequest); // 遍歷全部Object System.out.println("Objects:"); for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) { System.out.println(objectSummary.getKey()); } // 遍歷全部CommonPrefix System.out.println("\nCommonPrefixs:"); for (String commonPrefix : listing.getCommonPrefixes()) { System.out.println(commonPrefix); } 

輸出:

Objects:
fun/test.jpg

CommonPrefixs:
fun/movie/

返回的結果中, ObjectSummaries 的列表中給出的是fun目錄下的文件。而 CommonPrefixs 的列表中給出的是fun目錄下的全部子文件夾。能夠看出 fun/movie/001.avi , fun/movie/007.avi 兩個文件並無被列出來,由於它們屬於 fun 文件夾下的 movie 目錄。

獲取Object

簡單的讀取Object

咱們能夠經過如下代碼將Object讀取到一個流中:

public void getObject(String bucketName, String key) throws IOException { // 初始化OSSClient OSSClient client = ...; // 獲取Object,返回結果爲OSSObject對象 OSSObject object = client.getObject(bucketName, key); // 獲取ObjectMeta ObjectMetadata meta = object.getObjectMetadata(); // 獲取Object的輸入流 InputStream objectContent = object.getObjectContent(); // 處理Object ... // 關閉流 objectContent.close(); } 

`OSSObject 包含了Object的各類信息,包含Object所在的Bucket、Object的名稱、Metadata以及一個輸入流。咱們能夠經過操做輸入流將Object的內容讀取到文件或者內存中。而ObjectMetadata包含了Object上傳時定義的,ETag,Http Header以及自定義的元數據。

經過GetObjectRequest獲取Object

爲了實現更多的功能,咱們能夠經過使用 GetObjectRequest 來獲取Object。

// 初始化OSSClient
OSSClient client = ...; // 新建GetObjectRequest GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key); // 獲取0~100字節範圍內的數據 getObjectRequest.setRange(0, 100); // 獲取Object,返回結果爲OSSObject對象 OSSObject object = client.getObject(getObjectRequest); 

咱們經過 getObjectRequest 的 setRange 方法設置了返回的Object的範圍。咱們能夠用此功能實現文件的分段下載和斷點續傳。

GetObjectRequest能夠設置如下參數:

參數 說明
Range 指定文件傳輸的範圍。
ModifiedSinceConstraint 若是指定的時間早於實際修改時間,則正常傳送文件。不然拋出304 Not Modified異常。
UnmodifiedSinceConstraint 若是傳入參數中的時間等於或者晚於文件實際修改時間,則正常傳輸文件。不然拋出412 precondition failed異常
MatchingETagConstraints 傳入一組ETag,若是傳入指望的ETag和object的 ETag匹配,則正常傳輸文件。不然拋出412 precondition failed異常
NonmatchingEtagConstraints 傳入一組ETag,若是傳入的ETag值和Object的ETag不匹配,則正常傳輸文件。不然拋出304 Not Modified異常。
ResponseHeaderOverrides 自定義OSS返回請求中的一些Header。

修改 ResponseHeaderOverrides , 它提供了一系列的可修改參數,能夠自定義OSS的返回Header,以下表所示:

參數 說明
ContentType OSS返回請求的content-type頭
ContentLanguage OSS返回請求的content-language頭
Expires OSS返回請求的expires頭
CacheControl OSS返回請求的cache-control頭
ContentDisposition OSS返回請求的content-disposition頭
ContentEncoding OSS返回請求的content-encoding頭

直接下載Object到文件

咱們能夠經過下面的代碼直接將Object下載到指定文件:

// 新建GetObjectRequest
GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key); // 下載Object到文件 ObjectMetadata objectMetadata = client.getObject(getObjectRequest, new File("/path/to/file")); 

當使用上面方法將Object直接下載到文件時,方法返回ObjectMetadata對象。

只獲取ObjectMetadata

經過 getObjectMetadata 方法能夠只獲取ObjectMetadata而不獲取Object的實體。以下代碼所示:

ObjectMetadata objectMetadata = client.getObjectMetadata(bucketName, key); 

刪除Object

下面代碼刪除了一個Object:

public void deleteObject(String bucketName, String key) { // 初始化OSSClient OSSClient client = ...; // 刪除Object client.deleteObject(bucketName, key); } 

拷貝Object

拷貝一個Object

經過 copyObject 方法咱們能夠拷貝一個Object,以下面代碼:

public void copyObject(String srcBucketName, String srcKey, String destBucketName, String destKey) { // 初始化OSSClient OSSClient client = ...; // 拷貝Object CopyObjectResult result = client.copyObject(srcBucketName, srcKey, destBucketName, destKey); // 打印結果 System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified()); } 

copyObject 方法返回一個 CopyObjectResult 對象,對象中包含了新Object的ETag和修改時間。

經過CopyObjectRequest拷貝Object

也能夠經過 CopyObjectRequest 實現Object的拷貝:

// 初始化OSSClient
OSSClient client = ...; // 建立CopyObjectRequest對象 CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketName, srcKey, destBucketName, destKey); // 設置新的Metadata ObjectMetadata meta = new ObjectMetadata(); meta.setContentType("text/html"); copyObjectRequest.setNewObjectMetadata(meta); // 複製Object CopyObjectResult result = client.copyObject(copyObjectRequest); System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified()); 

CopyObjectRequest 容許用戶修改目的Object的ObjectMeta,同時也提供 ModifiedSinceConstraint , UnmodifiedSinceConstraint , MatchingETagConstraints , NonmatchingEtagConstraints 四個參數的設定, 用法與 GetObjectRequest 的參數類似,參見 GetObjectRequest的可設置參數

 

Object的分塊上傳

除了經過putObject接口上傳文件到OSS之外,OSS還提供了另一種上傳模式 —— Multipart Upload。用戶能夠在以下的應用場景內(但不只限於此),使用Multipart Upload上傳模式,如:

  • 須要支持斷點上傳。
  • 上傳超過100MB大小的文件。
  • 網絡條件較差,和OSS的服務器之間的連接常常斷開。
  • 須要流式地上傳文件。
  • 上傳文件以前,沒法肯定上傳文件的大小。

下面咱們將一步步介紹怎樣實現Multipart Upload。

分步完成Multipart Upload

假設咱們有一個文件,本地路徑爲 /path/to/file.zip 因爲文件比較大,咱們將其分塊傳輸到OSS中。

1. 初始化Multipart Upload

咱們使用 initiateMultipartUpload 方法來初始化一個分塊上傳事件:

String bucketName = "your-bucket-name"; String key = "your-key"; // 初始化OSSClient OSSClient client = ...; // 開始Multipart Upload InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(bucketName, key); InitiateMultipartUploadResult initiateMultipartUploadResult = client.initiateMultipartUpload(initiateMultipartUploadRequest); // 打印UploadId System.out.println("UploadId: " + initiateMultipartUploadResult.getUploadId()); 

咱們用 InitiateMultipartUploadRequest 來指定上傳Object的名字和所屬Bucket。在 InitiateMultipartUploadRequest 中,你也能夠設置 ObjectMetadata ,可是沒必要指定其中的 ContentLength (指定了也無效)。

initiateMultipartUpload 的返回結果中含有 UploadId ,它是區分分塊上傳事件的惟一標識,在後面的操做中,咱們將用到它。

2. 上傳分塊

接着,咱們把文件分塊上傳。

// 設置每塊爲 5M
final int partSize = 1024 * 1024 * 5; File partFile = new File("/path/to/file.zip"); // 計算分塊數目 int partCount = (int) (partFile.length() / partSize); if (partFile.length() % partSize != 0){ partCount++; } // 新建一個List保存每一個分塊上傳後的ETag和PartNumber List<PartETag> partETags = new ArrayList<PartETag>(); for(int i = 0; i < partCount; i++){ // 獲取文件流 FileInputStream fis = new FileInputStream(partFile); // 跳到每一個分塊的開頭 long skipBytes = partSize * i; fis.skip(skipBytes); // 計算每一個分塊的大小 long size = partSize < partFile.length() - skipBytes ? partSize : partFile.length() - skipBytes; // 建立UploadPartRequest,上傳分塊 UploadPartRequest uploadPartRequest = new UploadPartRequest(); uploadPartRequest.setBucketName(bucketName); uploadPartRequest.setKey(key); uploadPartRequest.setUploadId(initiateMultipartUploadResult.getUploadId()); uploadPartRequest.setInputStream(fis); uploadPartRequest.setPartSize(size); uploadPartRequest.setPartNumber(i + 1); UploadPartResult uploadPartResult = client.uploadPart(uploadPartRequest); // 將返回的PartETag保存到List中。 partETags.add(uploadPartResult.getPartETag()); // 關閉文件 fis.close(); } 

上面程序的核心是調用 uploadPart 方法來上傳每個分塊,可是要注意如下幾點:

  • uploadPart 方法要求除最後一個Part之外,其餘的Part大小都要大於5MB。可是Upload Part接口並不會當即校驗上傳Part的大小(由於不知道是否爲最後一塊);只有當Complete Multipart Upload的時候纔會校驗。
  • OSS會將服務器端收到Part數據的MD5值放在ETag頭內返回給用戶。爲了保證數據在網絡傳輸過程當中不出現錯誤,強烈推薦用戶在收到OSS的返回請求後,用該MD5值驗證上傳數據的正確性。
  • Part號碼的範圍是1~10000。若是超出這個範圍,OSS將返回InvalidArgument的錯誤碼。
  • 每次上傳part時都要把流定位到這次上傳塊開頭所對應的位置。
  • 每次上傳part以後,OSS的返回結果會包含一個 PartETag 對象,他是上傳塊的ETag與塊編號(PartNumber)的組合,在後續完成分塊上傳的步驟中會用到它,所以咱們須要將其保存起來。通常來說咱們將這些 PartETag 對象保存到List中。

3. 完成分塊上傳

完成分塊上傳很簡單,以下:

CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, key, initiateMultipartUploadResult.getUploadId(), partETags); // 完成分塊上傳 CompleteMultipartUploadResult completeMultipartUploadResult = client.completeMultipartUpload(completeMultipartUploadRequest); // 打印Object的ETag System.out.println(completeMultipartUploadResult.getETag()); 

上面代碼中的 partETags 就是第二部中保存的partETag的列表,OSS收到用戶提交的Part列表後,會逐一驗證每一個數據Part的有效性。當全部的數據Part驗證經過後,OSS將把這些數據part組合成一個完整的Object。

completeMultipartUpload 方法的返回結果中會包含拼裝後Object的ETag,用戶能夠和本地文件的MD5值進行校驗以保證數據的有效性。

取消分塊上傳事件

咱們能夠用 abortMultipartUpload 方法取消分塊上傳。

AbortMultipartUploadRequest abortMultipartUploadRequest = new AbortMultipartUploadRequest(bucketName, key, uploadId); // 取消分塊上傳 client.abortMultipartUpload(abortMultipartUploadRequest); 

獲取Bucket內全部分塊上傳事件

咱們能夠用 listMultipartUploads 方法獲取Bucket內全部上傳事件。

// 獲取Bucket內全部上傳事件
MultipartUploadListing listing = client.listMultipartUploads(listMultipartUploadsRequest); // 遍歷全部上傳事件 for (MultipartUpload multipartUpload : listing.getMultipartUploads()) { System.out.println("Key: " + multipartUpload.getKey() + " UploadId: " + multipartUpload.getUploadId()); } 

Note

 

默認狀況下,若是Bucket中的分塊上傳事件的數量大於1000,則只會返回1000個Object, 且返回結果中 IsTruncated 爲 false,並返回 NextKeyMarker 和 NextUploadMarker 做爲下此讀取的起點。若想增大返回分塊上傳事件數目,能夠修改 MaxUploads 參數,或者使用 KeyMarker 以及 UploadIdMarker 參數分次讀取。

獲取全部已上傳的塊信息

咱們能夠用 listParts 方法獲取某個上傳事件全部已上傳的塊。

ListPartsRequest listPartsRequest = new ListPartsRequest(bucketName, key, uploadId); // 獲取上傳的全部Part信息 PartListing partListing = client.listParts(listPartsRequest); // 遍歷全部Part for (PartSummary part : partListing.getParts()) { System.out.println("PartNumber: " + part.getPartNumber() + " ETag: " + part.getETag()); } 

Note

 

默認狀況下,若是Bucket中的分塊上傳事件的數量大於1000,則只會返回1000個Object, 且返回結果中 IsTruncated 爲 false,並返回 NextPartNumberMarker 做爲下此讀取的起點。若想增大返回分塊上傳事件數目,能夠修改 MaxParts 參數,或者使用 PartNumberMarker 參數分次讀取。

 

生成預簽名URL

若是你想把本身的資源發放給第三方用戶訪問,可是又不想開放Bucket的讀權限,能夠經過生成預簽名URL的形式提供給用戶一個臨時的訪問URL。在生成URL時,你能夠指定URL過時的時間,從而限制用戶長時間訪問。

生成一個預簽名的URL

以下代碼:

String bucketName = "your-bucket-name"; String key = "your-object-key"; // 設置URL過時時間爲1小時 Date expiration = new Date(new Date().getTime() + 3600 * 1000); // 生成URL URL url = client.generatePresignedUrl(bucketName, key, expiration); 

生成的URL默認以GET方式訪問,這樣,用戶能夠直接經過瀏覽器訪問相關內容。

生成其餘Http方法的URL

若是你想容許用戶臨時進行其餘操做(好比上傳,刪除Object),可能須要簽名其餘方法的URL,以下:

// 生成PUT方法的URL
URL url = client.generatePresignedUrl(bucketName, key, expiration, HttpMethod.PUT); 

經過傳入 HttpMethod.PUT 參數,用戶可使用生成的URL上傳Object。

添加用戶自定義參數(UserMetadata)

若是你想使用簽名的URL上傳Object,並指定UserMetadata等參數,能夠這樣作:

// 建立請求
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, key); // HttpMethod爲PUT generatePresignedUrlRequest.setMethod(HttpMethod.PUT); // 添加UserMetadata generatePresignedUrlRequest.addUserMetadata("key", "value"); // 生成預簽名的URL URL url = client.generatePresignedUrl(bucketName, key, expiration); 

須要注意的是,上述過程只是生成了簽名的URL,你仍須要在request header中添加UserMetadata的信息。

關於如何在Http請求中設置UserMetadata等參數,能夠參考 OSS REST API 文檔 中的相關內容。

 

異常

OSS Java SDK 中有兩種異常 ClientException 以及 OSSException , 他們都繼承自或者間接繼承自 RuntimeException 。

ClientException

ClientException指SDK內部出現的異常,好比未設置BucketName,網絡沒法到達等等。

OSSException

OSSException指服務器端錯誤,它來自於對服務器錯誤信息的解析。OSSException通常有如下幾個成員:

  • Code: OSS返回給用戶的錯誤碼。
  • Message: OSS給出的詳細錯誤信息。
  • RequestId: 用於惟一標識該次請求的UUID;當你沒法解決問題時,能夠憑這個RequestId來請求OSS開發工程師的幫助。
  • HostId: 用於標識訪問的OSS集羣(目前統一爲oss.aliyuncs.com)

下面是OSS中常見的異常:

錯誤碼 描述
AccessDenied 拒絕訪問
BucketAlreadyExists Bucket已經存在
BucketNotEmpty Bucket不爲空
EntityTooLarge 實體過大
EntityTooSmall 實體太小
FileGroupTooLarge 文件組過大
FilePartNotExist 文件Part不存在
FilePartStale 文件Part過期
InvalidArgument 參數格式錯誤
InvalidAccessKeyId Access Key ID不存在
InvalidBucketName 無效的Bucket名字
InvalidDigest 無效的摘要
InvalidObjectName 無效的Object名字
InvalidPart 無效的Part
InvalidPartOrder 無效的part順序
InvalidTargetBucketForLogging Logging操做中有無效的目標bucket
InternalError OSS內部發生錯誤
MalformedXML XML格式非法
MethodNotAllowed 不支持的方法
MissingArgument 缺乏參數
MissingContentLength 缺乏內容長度
NoSuchBucket Bucket不存在
NoSuchKey 文件不存在
NoSuchUpload Multipart Upload ID不存在
NotImplemented 沒法處理的方法
PreconditionFailed 預處理錯誤
RequestTimeTooSkewed 發起請求的時間和服務器時間超出15分鐘
RequestTimeout 請求超時
SignatureDoesNotMatch 簽名錯誤
TooManyBuckets 用戶的Bucket數目超過限制

 

 

         做者:王超    原文:http://aliyun_portal_storage.oss.aliyuncs.com/oss_api/oss_javahtml/index.html

相關文章
相關標籤/搜索