全部产品
存储与CDN 数据库 安全 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网
对象存储 OSS

管理文件

更新时间:2017-07-12 09:13:39

在OSS中,用户可以通过一系列的接口管理存储空间(Bucket)中的文件(Object),比如SetObjectAcl,GetObjectAcl,ListObjects,DeleteObject,CopyObject,DoesObjectExist等。Object的名字又称为key或object key。

Object是否存在

通过OSSClient.doesObjectExist判断文件(object)是否存在。

  1. // endpoint以杭州为例,其它region请按实际情况填写
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. // 创建OSSClient实例
  7. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  8. // Object是否存在
  9. boolean found = ossClient.doesObjectExist("<bucketName>", "<key>")
  10. // 关闭client
  11. ossClient.shutdown();

Object ACL

Object有四种访问权限:Default(默认),Private(私有读写), PublicRead(公共读私有写), PublicReadWrite(公共读写),含义如下:

权限 描述
默认 Objec是遵循Bucket的读写权限,即Bucket是什么权限,Object就是什么权限,Object的默认权限
私有读写 Object是私有资源,即只有该Object的Owner拥有该Object的读写权限,其他的用户没有权限操作该Object
公共读私有写 Object是公共读资源,即非Object Owner只有Object的读权限,而Object Owner拥有该Object的读写权限
公共读写 Object是公共读写资源,即所有用户拥有对该Object的读写权限

Object的权限优先级高于Bucket。例如Bucket是private的,而Object ACL是公共读写,则访问这个Object时,先判断Object的ACL,所有用户都拥有这个Object的访问权限,即使这个Bucket是private。如果某个Object从来没设置过ACL,则访问权限遵循Bucket ACL。

设置Object ACL

您可以通过OSSClient.setObjectAcl设置Object的权限。

权限 Java SDK对应值
私有读写 CannedAccessControlList.Private
公共读私有写 CannedAccessControlList.PublicRead
公共读写 CannedAccessControlList.PublicReadWrite

下面代码为Object设置ACL:

  1. // endpoint以杭州为例,其它region请按实际情况填写
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. // 创建OSSClient实例
  7. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  8. // 设置Object权限
  9. ossClient.setObjectAcl("<bucketName>", "<key>", CannedAccessControlList.PublicRead)
  10. // 关闭client
  11. ossClient.shutdown();

获取Object ACL

您可以通过OSSClient.getObjectAcl获取Object的权限。

  1. // endpoint以杭州为例,其它region请按实际情况填写
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. // 创建OSSClient实例
  7. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  8. //读取Object ACL
  9. ObjectAcl objectAcl = ossClient.getObjectAcl("<bucketName>", "<key>");
  10. System.out.println(objectAcl.getPermission().toString());
  11. // 关闭client
  12. ossClient.shutdown();

获取文件元信息(Object Meta)

文件元信息(Object Meta),是对用户上传到OSS的文件的属性描述,分为两种:HTTP标准属性(HTTP Headers)和User Meta(用户自定义元信息)。 文件元信息可以在各种方式上传或者拷贝文件时进行设置。更多文件元信息的介绍,请参看文件元信息

获取文件元信息可以使用OSSClient.getSimplifiedObjectMetaOSSClient.getObjectMetadatagetSimplifiedObjectMeta只能获取文件的ETag、Size(文件大小)、 LastModified(最后修改时间);getObjectMetadata能获取文件的全部元数据。getSimplifiedObjectMeta更轻量、更快

  1. // endpoint以杭州为例,其它region请按实际情况填写
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. // 创建OSSClient实例
  7. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  8. // 获取文件的部分元信息
  9. SimplifiedObjectMeta objectMeta = ossClient.getSimplifiedObjectMeta("<bucketName>", "<key>");
  10. System.out.println(objectMeta.getSize());
  11. System.out.println(objectMeta.getETag());
  12. System.out.println(objectMeta.getLastModified());
  13. // 获取文件的全部元信息
  14. ObjectMetadata metadata = ossClient.getObjectMetadata("<bucketName>", "<key>");
  15. System.out.println(metadata.getContentType());
  16. System.out.println(metadata.getLastModified());
  17. System.out.println(metadata.getExpirationTime());
  18. // 关闭client
  19. ossClient.shutdown();

列出存储空间中的文件

可以通过OSSClient.listObjects列出bucket里的Objects。listObjects有三类参数格式:

  • ObjectListing listObjects(String bucketName)
  • ObjectListing listObjects(String bucketName, String prefix)
  • ObjectListing listObjects(ListObjectsRequest listObjectsRequest)

前两类称为简单列举,最多返回100条object,参数prefix是指定返回Object的前缀。最后一类提供多种过滤功能,可以实现灵活的查询功能。

ObjectListing的参数如下:

参数 含义 方法
ObjectSummaries 限定返回的object meta。 List<OSSObjectSummary> getObjectSummaries()
Prefix 本次查询结果的开始前缀。 String getPrefix()
Delimiter 是一个用于对Object名字进行分组的字符。 String getDelimiter()
Marker 标明这次List Object的起点。 String getMarker()
MaxKeys 响应请求内返回结果的最大数目。 int getMaxKeys()
NextMarker 下一次List Object的起点。 String getNextMarker()
IsTruncated 指明是否所有的结果都已经返回。 boolean isTruncated()
CommonPrefixes 如果请求中指定了delimiter参数,则返回的包含CommonPrefixes元素。该元素标明以delimiter结尾,并有共同前缀的object的集合。 List<String> getCommonPrefixes()
EncodingType 指明返回结果中编码使用的类型。 String getEncodingType()

提示:

  • listObjects的完整代码请参考:GitHub

简单列举

列举出Bucket下的Object,最多100条object。

  1. // endpoint以杭州为例,其它region请按实际情况填写
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. // 创建OSSClient实例
  7. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  8. // 列举Object
  9. ObjectListing objectListing = ossClient.listObjects("<bucketName>", "<KeyPrifex>");
  10. List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
  11. for (OSSObjectSummary s : sums) {
  12. System.out.println("\t" + s.getKey());
  13. }
  14. // 关闭client
  15. ossClient.shutdown();

列举出Bucket下的指定前缀的Object,最多100条object。

  1. ObjectListing objectListing = ossClient.listObjects("<bucketName>", "<KeyPrifex>");
  2. List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
  3. for (OSSObjectSummary s : sums) {
  4. System.out.println("\t" + s.getKey());
  5. }

通过ListObjectsRequest列出文件

可以通过设置ListObjectsReques的参数实现各种灵活的查询功能。ListObjectsReques的可设置的参数如下:

参数 作用 方法
Prefix 限定返回的object key必须以prefix作为前缀。 setPrefix(String prefix)
Delimiter 是一个用于对Object名字进行分组的字符。所有名字包含指定的前缀且第一次出现delimiter字符之间的object作为一组元素——CommonPrefixes。 setDelimiter(String delimiter)
Marker 设定结果从marker之后按字母排序的第一个开始返回。 setMarker(String marker)
MaxKeys 限定此次返回object的最大数,如果不设定,默认为100,max-keys取值不能大于1000。 setMaxKeys(Integer maxKeys)
EncodingType 请求响应体中Object名称采用的编码方式,目前支持url setEncodingType(String encodingType)

指定最大返回条数

  1. // endpoint以杭州为例,其它region请按实际情况填写
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. // 创建OSSClient实例
  7. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  8. final int maxKeys = 200;
  9. // 列举Object
  10. ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest("<bucketName>").withMaxKeys(maxKeys));
  11. List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
  12. for (OSSObjectSummary s : sums) {
  13. System.out.println("\t" + s.getKey());
  14. }
  15. // 关闭client
  16. ossClient.shutdown();

返回指定前缀的object

最多返回100条。

  1. final String keyPrefix = "<keyPrefix>"
  2. ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest("<bucketName>").withPrefix(keyPrefix));
  3. List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
  4. for (OSSObjectSummary s : sums) {
  5. System.out.println("\t" + s.getKey());
  6. }

从指定Object后返回

不包括指定的Object,最多返回100条。

  1. final String keyMarker = "<keyMarker>"
  2. ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest("<bucketName>").withMarker(keyMarker));
  3. List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
  4. for (OSSObjectSummary s : sums) {
  5. System.out.println("\t" + s.getKey());
  6. }

分页获取所有Object

分页获取所有Object,每页maxKeys条Object。

  1. final int maxKeys = 200;
  2. String nextMarker = null;
  3. do {
  4. objectListing = ossClient.listObjects(new ListObjectsRequest("<bucketName>").withMarker(nextMarker).withMaxKeys(maxKeys));
  5. List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
  6. for (OSSObjectSummary s : sums) {
  7. System.out.println("\t" + s.getKey());
  8. }
  9. nextMarker = objectListing.getNextMarker();
  10. } while (objectListing.isTruncated());

分页获取所有特定Object后的Object

分页获取所有特定Object后的Object,每页maxKeys条Object。

  1. final int maxKeys = 200;
  2. String nextMarker = "<nextMarker>";
  3. do {
  4. objectListing = ossClient.listObjects(new ListObjectsRequest("<bucketName>").withMarker(nextMarker).withMaxKeys(maxKeys));
  5. List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
  6. for (OSSObjectSummary s : sums) {
  7. System.out.println("\t" + s.getKey());
  8. }
  9. nextMarker = objectListing.getNextMarker();
  10. } while (objectListing.isTruncated());

分页所有获取指定前缀的Object

分页所有获取指定前缀的Object,每页maxKeys条Object。

  1. final int maxKeys = 200;
  2. final String keyPrefix = "<keyPrefix>";
  3. String nextMarker = "<nextMarker>";
  4. do {
  5. objectListing = ossClient.listObjects(new ListObjectsRequest("<bucketName>").
  6. withPrefix(keyPrefix).withMarker(nextMarker).withMaxKeys(maxKeys));
  7. List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
  8. for (OSSObjectSummary s : sums) {
  9. System.out.println("\t" + s.getKey());
  10. }
  11. nextMarker = objectListing.getNextMarker();
  12. } while (objectListing.isTruncated());

指定Object名字编码

如果Object名字含有特殊字符,如 ' " & < >中文 等,需要进行编码传输。OSS目前支持 url 编码。

  1. final int maxKeys = 200;
  2. final String keyPrefix = "<keyPrefix>";
  3. String nextMarker = "<nextMarker>";
  4. ObjectListing objectListing;
  5. do {
  6. ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);
  7. listObjectsRequest.setPrefix(keyPrefix);
  8. listObjectsRequest.setMaxKeys(maxKeys);
  9. listObjectsRequest.setMarker(nextMarker);
  10. // 指定Object名称编码传输
  11. listObjectsRequest.setEncodingType("url");
  12. objectListing = ossClient.listObjects(listObjectsRequest);
  13. // Object解码
  14. for (OSSObjectSummary objectSummary: objectListing.getObjectSummaries()) {
  15. System.out.println("Key:" + URLDecoder.decode(objectSummary.getKey(), "UTF-8"));
  16. }
  17. // CommonPrefixe解码
  18. for (String commonPrefixes: objectListing.getCommonPrefixes()) {
  19. System.out.println("CommonPrefixes:" + URLDecoder.decode(commonPrefixes, "UTF-8"));
  20. }
  21. // NextMarker解码
  22. if (objectListing.getNextMarker() != null) {
  23. nextMarker = URLDecoder.decode(objectListing.getNextMarker(), "UTF-8");
  24. }
  25. } while (objectListing.isTruncated());

模拟文件夹功能

OSS是没有文件夹这个概念的,所有元素都是以Object来存储。创建模拟文件夹本质上来说是创建了一个size为0的Object。对于这个Object可以上传下载,只是控制台会对以”/“结尾的Object以文件夹的方式展示。

您可以通过 Delimiter 和 Prefix 参数的配合模拟出文件夹功能。Delimiter 和 Prefix 的组合效果是这样的:

  • 如果把 Prefix 设为某个文件夹名,就可以罗列以此 Prefix 开头的文件,即该文件夹下递归的所有的文件和子文件夹(目录)。文件名在Contents中显示。
  • 如果再把 Delimiter 设置为 “/” 时,返回值就只罗列该文件夹下的文件和子文件夹(目录),该文件夹下的子文件名(目录)返回在 CommonPrefixes 部分,子文件夹下递归的文件和文件夹不被显示。

提示:

假设Bucket中有4个文件: oss.jpg , fun/test.jpg , fun/movie/001.avi , fun/movie/007.avi , “/” 作为文件夹的分隔符。下面的示例展示了如何模拟文件夹功能。

列出存储空间内所有文件

当我们需要获取存储空间下的所有文件时,可以这样写:

  1. // 构造ListObjectsRequest请求
  2. ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);
  3. // 列出Object
  4. ObjectListing listing = ossClient.listObjects(listObjectsRequest);
  5. // 遍历所有Object
  6. System.out.println("Objects:");
  7. for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
  8. System.out.println(objectSummary.getKey());
  9. }
  10. // 遍历所有CommonPrefix
  11. System.out.println("CommonPrefixs:");
  12. for (String commonPrefix : listing.getCommonPrefixes()) {
  13. System.out.println(commonPrefix);
  14. }

输出:

  1. Objects:
  2. fun/movie/001.avi
  3. fun/movie/007.avi
  4. fun/test.jpg
  5. oss.jpg
  6. CommonPrefixs:

递归列出目录下所有文件

我们可以通过设置 Prefix 参数来获取某个目录(fun/)下所有的文件:

  1. // 构造ListObjectsRequest请求
  2. ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);
  3. listObjectsRequest.setPrefix("fun/");
  4. // 递归列出fun目录下的所有文件
  5. ObjectListing listing = ossClient.listObjects(listObjectsRequest);
  6. // 遍历所有Object
  7. System.out.println("Objects:");
  8. for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
  9. System.out.println(objectSummary.getKey());
  10. }
  11. // 遍历所有CommonPrefix
  12. System.out.println("\nCommonPrefixs:");
  13. for (String commonPrefix : listing.getCommonPrefixes()) {
  14. System.out.println(commonPrefix);
  15. }

输出:

  1. Objects:
  2. fun/movie/001.avi
  3. fun/movie/007.avi
  4. fun/test.jpg
  5. CommonPrefixs:

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

在 Prefix 和 Delimiter 结合的情况下,可以列出目录(fun/)下的文件和子目录:

  1. // 构造ListObjectsRequest请求
  2. ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);
  3. // "/" 为文件夹的分隔符
  4. listObjectsRequest.setDelimiter("/");
  5. // 列出fun目录下的所有文件和文件夹
  6. listObjectsRequest.setPrefix("fun/");
  7. ObjectListing listing = ossClient.listObjects(listObjectsRequest);
  8. // 遍历所有Object
  9. System.out.println("Objects:");
  10. for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
  11. System.out.println(objectSummary.getKey());
  12. }
  13. // 遍历所有CommonPrefix
  14. System.out.println("\nCommonPrefixs:");
  15. for (String commonPrefix : listing.getCommonPrefixes()) {
  16. System.out.println(commonPrefix);
  17. }

输出:

  1. Objects:
  2. fun/test.jpg
  3. CommonPrefixs:
  4. fun/movie/

提示:

  • 返回的结果中, ObjectSummaries 的列表中给出的是fun目录下的文件。
  • 而 CommonPrefixs 的列表中给出的是fun目录下的所有子文件夹。可以看出 fun/movie/001.avi , fun/movie/007.avi 两个文件并没有被列出来,因为它们属于fun文件夹下的movie目录。

删除文件

删除单个文件:

您可以通过OSSClient.deleteObject删除单个文件。

  1. // endpoint以杭州为例,其它region请按实际情况填写
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. // 创建OSSClient实例
  7. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  8. // 删除Object
  9. ossClient.deleteObject("<bucketName>", "<key>");
  10. // 关闭client
  11. ossClient.shutdown();

删除多个文件:

您可以通过OSSClient.deleteObjects批量删除文件。

  1. public DeleteObjectsResult deleteObjects(DeleteObjectsRequest deleteObjectsRequest)

每次最多删除1000个Object,并提供两种返回模式:详细(verbose)模式和简单(quiet)模式:

  • 详细模式:返回的成功删除Object的结果,即DeleteObjectsResult.getDeletedObjects,默认模式;
  • 简单模式:返回的删除过程中出错的Object结果,即DeleteObjectsResult.getDeletedObjects。

DeleteObjectsRequest可设置参数如下:

参数 作用 方法
Keys 需要删除的Objects setKeys(List<String>)
Quiet 返回模式,默认详细模式;true简单模式,false详细模式 setQuiet(boolean)
EncodingType 指定对返回的Key进行编码,目前支持url setEncodingType(String)

DeleteObjectsResult的参数如下:

参数 含义 方法
deletedObjects 删除结果,详细模式时成功删除的objects,简单模式时删除失败的objects List<String> getDeletedObjects()
EncodingType deletedObjects中Key的进行编码,为空没有编码 getEncodingType()
  1. // endpoint以杭州为例,其它region请按实际情况填写
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. // 创建OSSClient实例
  7. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  8. // 删除Objects
  9. List<String> keys = new ArrayList<String>();
  10. keys.add("key0");
  11. keys.add("key1");
  12. keys.add("key2");
  13. DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest("<bucketName>").withKeys(keys));
  14. List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
  15. // 关闭client
  16. ossClient.shutdown();

提示:

  • 批量删除文件的完整代码请参考:GitHub

拷贝文件

在同一个区域(杭州,深圳,青岛等)中,可以将Object从一个Bucket复制到另外一个Bucket。您可以通过OSSClient.copyObject

  • CopyObjectResult copyObject(String sourceBucketName, String sourceKey, String destinationBucketName, String destinationKey)
  • CopyObjectResult copyObject(CopyObjectRequest copyObjectRequest)

第一个方法指定源Bucket/Key和目标源Bucket/Key,目标object的内容和元数据与源object相同,称为简单拷贝。第二个方法允许指定目标文件的原因数据、允许指定拷贝的限制条件。如果拷贝操作的源Object地址和目标Object地址相同,则直接替换源Object的meta信息。

CopyObjectRequest可设置参数如下:

参数 作用 方法
sourceBucketName 源Object所在的Bucket的名称 setSourceBucketName(String sourceBucketName)
sourceKey 源Object的Key setSourceKey(String sourceKey)
destinationBucketName 目标Object所在的Bucket的名称 setDestinationBucketName(String destinationBucketName)
destinationKey 目标Object的Key setDestinationKey(String destinationKey)
newObjectMetadata 目标Object的元信息 setNewObjectMetadata(ObjectMetadata newObjectMetadata)
matchingETagConstraints 拷贝的限制条件,如果源Object的ETAG值和提供的ETAG相等,则执行拷贝操作;否则返回错误 setMatchingETagConstraints(List<String> matchingETagConstraints)
nonmatchingEtagConstraints 拷贝的限制条件,如果源Object的ETAG值和用户提供的ETAG不相等,则执行拷贝操作;否则返回错误 setNonmatchingETagConstraints(List<String> nonmatchingEtagConstraints)
unmodifiedSinceConstraint 拷贝的限制条件,如果传入参数中的时间等于或者晚于文件实际修改时间,则正常拷贝;否则返回错误 setUnmodifiedSinceConstraint(Date unmodifiedSinceConstraint)
modifiedSinceConstraint 拷贝的限制条件,如果源Object自从用户指定的时间以后被修改过,则执行拷贝操作;否则返回错误 setModifiedSinceConstraint(Date modifiedSinceConstraint)

CopyObjectRequest的参数如下:

参数 含义 方法
etag OSS Object唯一性标志 String getETag()
lastModified Object最后修改时间 Date getLastModified()

注意:

  • 用户需要有源Object的操作权限,否则会无法完成操作。
  • 该操作不支持跨Region拷贝数据。比如:不支持将杭州Bucket里的Object拷贝到青岛。
  • 该操作支持的最大Object大小为1GB。

简单拷贝

  1. // endpoint以杭州为例,其它region请按实际情况填写
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. // 创建OSSClient实例
  7. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  8. // 拷贝Object
  9. CopyObjectResult result = ossClient.copyObject("<srcBucketName>", "<srcKey>", "<destBucketName>", "<destKey>");
  10. System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified());
  11. // 关闭client
  12. ossClient.shutdown();

通过CopyObjectRequest拷贝

也可以通过 CopyObjectRequest 实现Object的拷贝:

  1. // endpoint以杭州为例,其它region请按实际情况填写
  2. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  3. // 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建
  4. String accessKeyId = "<yourAccessKeyId>";
  5. String accessKeySecret = "<yourAccessKeySecret>";
  6. // 创建OSSClient实例
  7. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  8. // 创建CopyObjectRequest对象
  9. CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketName, srcKey, destBucketName, destKey);
  10. // 设置新的Metadata
  11. ObjectMetadata meta = new ObjectMetadata();
  12. meta.setContentType("text/html");
  13. copyObjectRequest.setNewObjectMetadata(meta);
  14. // 复制Object
  15. CopyObjectResult result = ossClient.copyObject(copyObjectRequest);
  16. System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified());
  17. // 关闭client
  18. ossClient.shutdown();

拷贝大文件

CopyObject只能copy小于1GB的文件,大文件需要使用分片拷贝(Upload Part Copy)。分片拷贝更详细的说明,请参考Upload Part Copy。分片拷贝分为三步:

  • 初始化分片拷贝任务OSSClient.initiateMultipartUpload
  • 分片拷贝OSSClient.uploadPartCopy,除最后一个分片外,其它的分片大小都要大于100KB;
  • 提交分片拷贝任务OSSClient.completeMultipartUpload

提示:

  • 分片拷贝的完整代码请参考:GitHub
  1. String sourceBucketName = "<sourceBucketName>";
  2. String sourceKey = "<sourceKey>";
  3. String targetBucketName = "<targetBucketName>";
  4. String targetKey = "<targetKey>";
  5. // 得到被拷贝object大小
  6. ObjectMetadata objectMetadata = ossClient.getObjectMetadata(sourceBucketName, sourceKey);
  7. long contentLength = objectMetadata.getContentLength();
  8. // 分片大小,10MB
  9. long partSize = 1024 * 1024 * 10;
  10. // 计算分块数目
  11. int partCount = (int) (contentLength / partSize);
  12. if (contentLength % partSize != 0) {
  13. partCount++;
  14. }
  15. System.out.println("total part count:" + partCount);
  16. // 初始化拷贝任务
  17. InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(targetBucketName, targetKey);
  18. InitiateMultipartUploadResult initiateMultipartUploadResult = ossClient.initiateMultipartUpload(initiateMultipartUploadRequest);
  19. String uploadId = initiateMultipartUploadResult.getUploadId();
  20. // 分片拷贝
  21. List<PartETag> partETags = new ArrayList<PartETag>();
  22. for (int i = 0; i < partCount; i++) {
  23. // 计算每个分块的大小
  24. long skipBytes = partSize * i;
  25. long size = partSize < contentLength - skipBytes ? partSize : contentLength - skipBytes;
  26. // 创建UploadPartCopyRequest
  27. UploadPartCopyRequest uploadPartCopyRequest =
  28. new UploadPartCopyRequest(sourceBucketName, sourceKey, targetBucketName, targetKey);
  29. uploadPartCopyRequest.setUploadId(uploadId);
  30. uploadPartCopyRequest.setPartSize(size);
  31. uploadPartCopyRequest.setBeginIndex(skipBytes);
  32. uploadPartCopyRequest.setPartNumber(i + 1);
  33. UploadPartCopyResult uploadPartCopyResult = ossClient.uploadPartCopy(uploadPartCopyRequest);
  34. // 将返回的PartETag保存到List中
  35. partETags.add(uploadPartCopyResult.getPartETag());
  36. }
  37. // 提交分片拷贝任务
  38. CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(
  39. targetBucketName, targetKey, uploadId, partETags);
  40. ossClient.completeMultipartUpload(completeMultipartUploadRequest);

提示:

  • 分片拷贝时,可以指定目标object的元信息,通过InitiateMultipartUploadRequest指定;
  • 分片拷贝也支持限定条件,通过UploadPartCopyRequest指定。

解冻归档文件

归档(Archive)类型的Object,解冻之后(Restore)后才能读取。详细说明请参看 归档存储。归档文件的状态变换过程如下:

  • 归档类型的文件初始时处于冷冻状态;
  • 提交解冻(Restore)操作后,服务端执行解冻,文件处于解冻中;
  • 完成解冻后,可以读取Object;
  • 解冻状态默认持续1天,最多延长7天,之后文件又回到冷冻状态。
  1. ObjectMetadata objectMetadata = ossClient.getObjectMetadata(bucketName, key);
  2. // check whether the object is archive class
  3. StorageClass storageClass = objectMetadata.getObjectStorageClass();
  4. if (storageClass == StorageClass.Archive) {
  5. // restore object
  6. ossClient.restoreObject(bucketName, key);
  7. // wait for restore completed
  8. do {
  9. Thread.sleep(1000);
  10. objectMetadata = ossClient.getObjectMetadata(bucketName, key);
  11. } while (!objectMetadata.isRestoreCompleted());
  12. }
  13. // get restored object
  14. OSSObject ossObject = ossClient.getObject(bucketName, key);
  15. ossObject.getObjectContent().close();

提示:

  • 上述示例的完整代码请参看 GitHUb
  • 非归档类型的文件,不要调用 restoreObject 接口。
本文导读目录