步骤以下:php
通过上面几步以后,你就能够在工程中使用OSS JAVA SDK了。html
在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完成一些基本的操做。浏览器
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
Bucket是OSS上的命名空间,至关于数据的容器,能够存储若干数据实体(Object)。
你能够按照下面的代码新建一个Bucket:
public void createBucket(String bucketName) { // 初始化OSSClient OSSClient client = ...; // 新建一个Bucket client.createBucket(bucketName); }
因为Bucket的名字是全局惟一的,因此尽可能保证你的 bucketName 不与别人重复。
关于Bucket的命名规范,参见 Bucket命名规范。
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 。
当你完成一系列上传后,可能会须要查看在某个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>)。
你能够参考下面的代码简单地实现一个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是OSS服务的Java客户端,它为调用者提供了一系列的方法,用于和OSS服务进行交互。
新建一个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的时候传入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能指定的全部参数以下表所示:
参数 | 说明 |
---|---|
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是OSS上的命名空间,也是计费、权限控制、日志记录等高级功能的管理实体;Bucket名称在整个OSS服务中具备全局惟一性,且不能修改;存储在OSS上的每一个Object必须都包含在某个Bucket中。一个应用,例如图片分享网站,能够对应一个或多个Bucket。一个用户最多可建立10个Bucket,但每一个Bucket中存放的Object的数量和大小总和没有限制,用户不须要考虑数据的可扩展性。
Bucket的命名有如下规范:
以下代码能够新建一个Bucket:
String bucketName = "my-bucket-name"; // 初始化OSSClient OSSClient client = ...; // 新建一个Bucket client.createBucket(bucketName);
因为Bucket的名字是全局惟一的,因此尽可能保证你的 bucketName 不与别人重复。
下面代码能够列出用户全部的Bucket:
// 获取用户的Bucket列表
List<Bucket> buckets = client.listBuckets(); // 遍历Bucket for (Bucket bucket : buckets) { System.out.println(bucket.getName()); }
有时候,咱们的需求只是判断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:
String bucketName = "your-bucket-name"; // 删除Bucket client.deleteBucket(bucketName)
须要注意的是,若是Bucket不为空(Bucket中有Object),则Bucket没法删除,必须清空Bucket后才能成功删除。
OSS提供Bucket级别的权限访问控制,Bucket目前有三种访问权限:public-read-write,public-read和private。它们的含义以下:
用户新建立一个新Bucket时,若是不指定Bucket权限,OSS会自动为该Bucket设置private权限。对于一个已经存在的Bucket,只有它的建立者能够经过OSS的所提供的接口修改其访问权限。
下面代码将Bucket的权限设置为了private。
String bucketName = "your-bucket-name"; client.setBucketAcl(bucketName, CannedAccessControlList.Private);
CannedAccessControlList是枚举类型,包含三个值: Private 、 PublicRead 、 PublicReadWrite ,它们分别对应相关权限。
在OSS中,用户操做的基本数据单元是Object。单个Object最大容许存储5TB的数据。Object包含key、meta和data。其中,key是Object的名字;meta是用户对该object的描述,由一系列name-value对组成;data是Object的数据。
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检验上传的文件与本地的是否一致。
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的分块上传 这一章中作介绍。
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下的全部文件时,能够这样写:
// 构造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读取到一个流中:
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。
// 初始化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下载到指定文件:
// 新建GetObjectRequest
GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key); // 下载Object到文件 ObjectMetadata objectMetadata = client.getObject(getObjectRequest, new File("/path/to/file"));
当使用上面方法将Object直接下载到文件时,方法返回ObjectMetadata对象。
经过 getObjectMetadata 方法能够只获取ObjectMetadata而不获取Object的实体。以下代码所示:
ObjectMetadata objectMetadata = client.getObjectMetadata(bucketName, key);
下面代码删除了一个Object:
public void deleteObject(String bucketName, String key) { // 初始化OSSClient OSSClient client = ...; // 删除Object client.deleteObject(bucketName, key); }
经过 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的拷贝:
// 初始化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的可设置参数。
除了经过putObject接口上传文件到OSS之外,OSS还提供了另一种上传模式 —— Multipart Upload。用户能够在以下的应用场景内(但不只限于此),使用Multipart Upload上传模式,如:
下面咱们将一步步介绍怎样实现Multipart Upload。
假设咱们有一个文件,本地路径为 /path/to/file.zip 因为文件比较大,咱们将其分块传输到OSS中。
咱们使用 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 ,它是区分分块上传事件的惟一标识,在后面的操做中,咱们将用到它。
接着,咱们把文件分块上传。
// 设置每块为 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 方法来上传每个分块,可是要注意如下几点:
完成分块上传很简单,以下:
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);
咱们能够用 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 参数分次读取。
若是你想把本身的资源发放给第三方用户访问,可是又不想开放Bucket的读权限,能够经过生成预签名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方式访问,这样,用户能够直接经过浏览器访问相关内容。
若是你想容许用户临时进行其余操做(好比上传,删除Object),可能须要签名其余方法的URL,以下:
// 生成PUT方法的URL
URL url = client.generatePresignedUrl(bucketName, key, expiration, HttpMethod.PUT);
经过传入 HttpMethod.PUT 参数,用户可使用生成的URL上传Object。
若是你想使用签名的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指SDK内部出现的异常,好比未设置BucketName,网络没法到达等等。
OSSException指服务器端错误,它来自于对服务器错误信息的解析。OSSException通常有如下几个成员:
下面是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