全部产品
弹性计算 会员服务 网络 安全 移动云 数加·大数据分析及展现 数加·大数据应用 管理与监控 云通信 阿里云办公 培训与认证 更多
存储与CDN 数据库 域名与网站(万网) 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网 智能硬件
对象存储 OSS

上传文件

更新时间:2018-05-08 18:11:51

在OSS中,用户操作的基本数据单元是文件(Object)。OSS Java SDK提供了丰富的文件上传接口,您可以通过以下方式上传文件:

  • 流式上传
  • 文件上传
  • 追加上传
  • 分片上传
  • 断点续传上传

每一种上传方式都具有各自的特性,其特性如下:

  • 流式上传、文件上传、追加上传的文件(Object)最大不能超过5GB。
  • 当文件较大时,请使用分片上传,分片上传文件大小不能超过48.8TB。
  • 断点续传上传支持并发、断点续传、自定义分片大小。
  • 断点续传是分片上传的封装和加强。大文件上传推荐使用断点续传。

简单上传

流式上传和文件上传通称为简单上传。流式上传使用InputStream作为Object数据源。文件上传使用本地文件作为Object数据源。

提示:简单上传的完整代码请参考:GitHub

流式上传

您可以使用ossClient.putObject上传您的数据流到OSS。

上传字符串

  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. String content = "Hello OSS";
  10. ossClient.putObject("<yourBucketName>", "<yourKey>", new ByteArrayInputStream(content.getBytes()));
  11. // 关闭client
  12. ossClient.shutdown();

上传byte数组

  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. // 上传byte数组
  9. byte[] content = "Hello OSS".getBytes();
  10. ossClient.putObject("<yourBucketName>", "<yourKey>", new ByteArrayInputStream(content));
  11. // 关闭client
  12. 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. InputStream inputStream = new URL("https://www.aliyun.com/").openStream();
  10. ossClient.putObject("<yourBucketName>", "<yourKey>", inputStream);
  11. // 关闭client
  12. ossClient.shutdown();

上传文件流

  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. InputStream inputStream = new FileInputStream("localFile");
  10. ossClient.putObject("<yourBucketName>", "<yourKey>", inputStream);
  11. // 关闭client
  12. 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. ossClient.putObject("<yourBucketName>", "<yourKey>", new File("localFile"));
  10. // 关闭client
  11. ossClient.shutdown();

设置元信息

文件元信息,是对上传到OSS的文件的属性描述,分为两种:HTTP标准属性(HTTP Headers)和User Meta(用户自定义元信息)。 文件元信息可以在上传(包括流式上传、文件上传、追加上传、分片上传、断点续传)或拷贝文件时进行设置。元信息的名称大小写不敏感。更多文件元信息的介绍,请参看文件元信息

设定HTTP Header

OSS允许用户自定义HTTP Header。HTTP Header请参考RFC2616。几个常用的HTTP Header说明如下:

参数 类型 描述 默认值
Content-MD5 字符串 MD5格式数据。设置了该参数后OSS会启用文件内容MD5校验,把您提供的MD5与文件的MD5比较,不一致会抛出错误。
Content-Type 字符串 文件类型。指文件的MIME,用于定义文件的类型及网页编码,决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成,如果没有扩展名则填默认值。 application/octet-stream
Content-Disposition 字符串 指定该文件被下载时的名称。Content-disposition是 MIME 协议的扩展,MIME 协议指示MIME 用户代理如何显示附加的文件。
Content-Length 整数型 指定该文件的大小。上传的文件的长度,如超过流/文件的长度,则会被截断,为流/文件的长度。如不足,则为上传的文件大小的实际长度。 流/文件的长度
Expires 日期 指定该文件缓存过期时间。格式是格林威治时间(GMT)。
Cache-Control 字符串 指定该文件被下载时的网页的缓存行为。
Content-Encoding 字符串 指定该文件被下载时的内容编码格式。
  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 content = "Hello OSS";
  7. // 创建上传Object的Metadata
  8. ObjectMetadata meta = new ObjectMetadata();
  9. // 设置上传MD5校验
  10. String md5 = BinaryUtil.toBase64String(BinaryUtil.calculateMd5(content.getBytes()));
  11. meta.setContentMD5(md5);
  12. // 设置上传的内容类型
  13. meta.setContentType("text/plain");
  14. // 设置内容被下载时的名称
  15. meta.setContentDisposition("Download File Name");
  16. // 设置上传文件的长度
  17. meta.setContentLength(content.length());
  18. //设置内容被下载时的网页的缓存行为
  19. meta.setCacheControl("Download Action");
  20. //设置缓存过期时间
  21. meta.setExpirationTime(DateUtil.parseIso8601Date("2022-10-12T00:00:00.000Z"));
  22. //设置被下载时的内容编码格式
  23. meta.setContentEncoding("utf-8");
  24. // 创建OSSClient实例
  25. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  26. // 上传文件
  27. ossClient.putObject("<yourBucketName>", "<yourKey>", new ByteArrayInputStream(content.getBytes()), meta);
  28. // 关闭client
  29. ossClient.shutdown();

提示:

  • ObjectMetadata提供常用的HTTP Header的设置信息,比如Content-MD5、Content-Type 、 Content-Length、Content-Disposition 、Content-Encoding 、 Expires、x-oss-server-side-encryption等。
  • 使用ObjectMetadata.setHeader(String key, Object value)设置Header。

用户自定义元信息

OSS支持用户通过自定义Object的元信息来对Object进行描述。

  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 content = "Hello OSS";
  7. // 创建OSSClient实例
  8. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  9. // 创建上传Object的Metadata
  10. ObjectMetadata meta = new ObjectMetadata();
  11. // 设置自定义元信息name的值为my-data
  12. meta.addUserMetadata("property", "property-value");
  13. // 上传文件
  14. ossClient.putObject("<yourBucketName>", "<yourKey>", new ByteArrayInputStream(content.getBytes()), meta);
  15. // 关闭client
  16. ossClient.shutdown();

提示:

  • 在上面代码中,用户自定义了一个名称为“property”,值为“property-value”的元信息。
  • 文件的元信息可以通过ossClient.getObjectMetadata获取。
  • 下载文件的时,文件的元信息也会同时下载。
  • 一个文件可以有多个元信息,总大小不能超过8KB。

创建文件夹

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

  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. final String keySuffixWithSlash = "parent_directory/";
  9. ossClient.putObject("<bucketName>", keySuffixWithSlash, new ByteArrayInputStream(new byte[0]));
  10. // 关闭client
  11. ossClient.shutdown();

提示:

  • 对于多级目录,您只需要创建最后一级即可,比如对于三级目录dir1/dir2/dir3/,您只需要创建dir1/dir2/dir3/即可,因为在创建dir1/dir2/dir3/目录时,已经默认为您创建好了dir1/、dir1/dir2/前两级目录,所以dir1/、dir1/dir2/不需要再单独创建。
  • 更多内容请参考 管理文件

追加上传

对于简单上传、分片上传、断点续传上传,创建的Object都是Normal类型,这种Object在上传结束之后内容就是固定的,只能读取,不能修改。如果Object内容发生了改变,只能重新上传同名的Object来覆盖之前的内容,这也是OSS和普通文件系统使用的一个重大区别。正因为这种特性,在很多应用场景下会很不方便,比如视频监控、视频直播领域等,视频数据在实时的不断产生。

为此,OSS提供了通过追加上传(Append Object)的方式在一个Object后面直接追加内容的功能。通过这种方式操作的Object的类型为Appendable Object,而其他的方式上传的Object类型为Normal Object。每次追加上传的数据都能够即时可读。

您可以使用ossClient.appendObject追加上传文件。

  1. AppendObjectResult appendObject(AppendObjectRequest appendObjectRequest)

AppendObjectRequest可设置参数如下:

参数 描述 如何设置值
BucketName bucket名称 setBucketName(String bucketName)
Key object名称 setKey(String key)
InputStream 待追加的内容,InputStream/File二选一 setInputStream(InputStream inputStream)
File 待追加的内容,InputStream/File二选一 setFile(File file)
ObjectMetadata 指定Object的元信息,第一次追加时有效 setMetadata(ObjectMetadata metadata)
Position Object追加位置 setPosition(Long position)

AppendObjectResult的参数如下:

参数 描述 方法
nextPosition 指明下一次请求应当提供的position。即Object当前的长度。 Long getNextPosition()
objectCRC64 Object的64位CRC值。该64位CRC根据ECMA-182标准计算得出 String getObjectCRC64()

提示: 追加上传的完整代码请参考:GitHub

  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 content = "Hello OSS";
  7. // 创建OSSClient实例
  8. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  9. AppendObjectRequest appendObjectRequest = new AppendObjectRequest("<yourBucketName>",
  10. "<yourKey>", new ByteArrayInputStream(content.getBytes()));
  11. // 第一次追加
  12. appendObjectRequest.setPosition(0L);
  13. AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest);
  14. // 第二次追加
  15. appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
  16. appendObjectResult = ossClient.appendObject(appendObjectRequest);
  17. // 第三次追加
  18. appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
  19. appendObjectResult = ossClient.appendObject(appendObjectRequest);
  20. // 关闭client
  21. ossClient.shutdown();

提示:

  • 追加上传的次数没有限制,文件大小上限为5GB。更大的文件请使用分片上传。
  • 追加类型的文件(Append Object)暂时不支持copyObject操作。

断点续传上传

当上传大文件时,如果网络不稳定或者程序崩溃了,则整个上传就失败了。用户不得不重头再来,这样做不仅浪费资源,在网络不稳定的情况下,往往重试多次还是无法完成上传。OSS提供ossClient.uploadFile方法来实现断点续传上传,参数是UploadFileRequest,该方法有以下参数:

参数 描述 是否必选 默认值 如何设置值
bucket 存储空间名字 必选参数 通过构造方法设置
key 上传到OSS的Object名字 必选参数 通过构造方法设置
uploadFile 待上传的本地文件 必选参数 通过构造方法或setUploadFile设置
partSize 分片大小,从100KB到5GB,单位是Byte 可选参数 默认100K 通过setPartSize设置
taskNum 分片上传并发数 可选参数 默认为1 通过setTaskNum设置
enableCheckpoint 是否开启断点续传 可选参数 默认断点续传功能关闭 通过setEnableCheckpoint设置
checkpointFile 开启断点续传时,需要在本地记录分片上传的结果,如果上传失败,下次不会再上传已经成功的分片 可选参数 默认与待上传的本地文件同目录,为uploadFile.ucp 可以通过setCheckpointFile设置
objectMetadata Object的元数据 可选参数 用户可以通过setObjectMetadata设置
callback 上传成功后的回调 可选参数 用户可以通过setCallback设置

断点续传上传其实现的原理是,将要上传的文件分成若干个分片分别上传,所有分片都上传成功后,将所有分片合并成完整的文件,完成整个文件的上传。在上传的过程中会记录当前上传的进度信息(记录在checkpoint文件中),如果上传过程中某一分片上传失败,再次上传时会从checkpoint文件中记录的点继续上传。这要求再次调用时要指定与上次相同的checkpoint文件。上传完成后,checkpoint文件会被删除。

  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. UploadFileRequest uploadFileRequest = new UploadFileRequest("<yourBucketName>", "<yourKey>");
  10. // 指定上传的本地文件
  11. uploadFileRequest.setUploadFile("<yourLocalFile>");
  12. // 指定上传并发线程数
  13. uploadFileRequest.setTaskNum(5);
  14. // 指定上传的分片大小
  15. uploadFileRequest.setPartSize(1 * 1024 * 1024);
  16. // 开启断点续传
  17. uploadFileRequest.setEnableCheckpoint(true);
  18. // 断点续传上传
  19. ossClient.uploadFile(uploadFileRequest);
  20. // 关闭client
  21. ossClient.shutdown();

提示:

  • 断点续传是分片上传的封装和加强,是用分片上传实现的。
  • 文件较大或网络环境较差时,推荐使用分片上传。
  • 断点续传支持指定ObjectMetadata,并支持上传完成回调(Callback)。

分片上传

对于大文件上传,可以将其切分成片后上传。分片上传(Multipart Upload)主要适用于以下场景:

  • 需要断点上传。
  • 上传超过100MB大小的文件。
  • 网络条件较差,和OSS的服务器之间的链接经常断开。
  • 上传文件之前,无法确定上传文件的大小。

分片上传(Multipart Upload)分为如下3个步骤:

  1. 初始化一个分片上传事件(initiateMultipartUpload)。
  2. 逐个或并行上传分片(uploadPart)。
  3. 完成分片上传(completeMultipartUpload)或取消分片上传(abortMultipartUpload)。

提示:分片上传的完整代码请参考:GitHub

步骤1:初始化一个分片上传事件

使用Multipart Upload模式传输数据前,必须先通知OSS初始化一个Multipart Upload事件。该操作会返回一个OSS服务器创建的全局唯一的Upload ID,用于标识本次Multipart Upload事件。用户可以根据这个ID来发起相关的操作,如中止Multipart Upload、查询Multipart Upload等。

调用ossClient.initiateMultipartUpload来初始化一个分片上传事件,示例代码如下:

  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 key = "<yourKey>";
  8. // 创建OSSClient实例
  9. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  10. InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, key);
  11. InitiateMultipartUploadResult result = ossClient.initiateMultipartUpload(request);
  12. String uploadId = result.getUploadId();

提示:

  • 用InitiateMultipartUploadRequest指定上传文件的名字和所属存储空间(bucketName)。
  • 在InitiateMultipartUploadRequest中,您也可以设置ObjectMeta。
  • initiateMultipartUpload 的返回结果中含有UploadId,它是区分分片上传事件的唯一标识,在后面的操作中将用到它。

步骤2:上传分片

初始化一个Multipart Upload之后,可以根据指定的Object名称和Upload ID来分片上传数据,每个分片被称为一个Part。每一个上传的Part都有一个标识它的号码——分片号(part number,取值范围是1~10,000)。对于同一个Upload ID,分片号不但唯一标识这一块数据,也标识了这块数据在整个文件内的相对位置。如果用同一个分片号码上传了新的数据,那么OSS上已有的这个分片的数据将被覆盖。除了最后一块Part以外,其他的Part最小为100KB。最后一块Part没有大小限制。每个分片不需要按顺序上传,甚至可以在不同客户端上传,OSS会按照分片号排序组成完整的文件。

调用ossClient.uploadPart上传分片的示例代码如下:

  1. List<PartETag> partETags = new ArrayList<PartETag>();
  2. InputStream instream = new FileInputStream(new File("<localFile>"));
  3. UploadPartRequest uploadPartRequest = new UploadPartRequest();
  4. uploadPartRequest.setBucketName(bucketName);
  5. uploadPartRequest.setKey(key);
  6. uploadPartRequest.setUploadId(uploadId);
  7. uploadPartRequest.setInputStream(instream);
  8. // 设置分片大小,除最后一个分片外,其它分片要大于100KB
  9. uploadPartRequest.setPartSize(100 * 1024);
  10. // 设置分片号,范围是1~10000,
  11. uploadPartRequest.setPartNumber(1);
  12. UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
  13. partETags.add(uploadPartResult.getPartETag());

注意:

  • uploadPart 方法要求除最后一个Part以外,其他的Part大小都要大于100KB。但是Upload Part接口并不会立即校验上传Part的大小(因为不知道是否为最后一块)。只有当调用Complete Multipart Upload的时候才会校验。
  • OSS会将服务器端收到的Part数据的MD5值放在ETag头内返回给用户。
  • 为了保证数据在网络传输过程中不出现错误,SDK会自动设置Content-MD5,OSS会计算上传数据的MD5值与SDK计算的MD5值比较,如果不一致返回InvalidDigest错误码。
  • Part号码的范围是1~10000。如果超出这个范围,OSS将返回InvalidArgument的错误码。
  • 每次上传Part时都要把流定位到此次上传块开头所对应的位置。
  • 每次上传Part之后,OSS的返回结果会包含一个 PartETag 对象,他是此Part上传块的ETag与块编号(PartNumber)的组合, 在后续完成分片上传的步骤中会用到它,因此我们需要将其保存起来。一般来讲我们将这些 PartETag 对象保存到分片列表(partETags)。

步骤3:完成分片上传

所有分片上传完成后,需要调用CompleteMultipartUpload接口来完成整个文件的分片上传。在执行该操作时,需要提供所有有效的partETags(包括PartNumber和ETag)。OSS收到提交的partETags后,会逐一验证每个Part的有效性。当所有的数据Part验证通过后,OSS将把这些Part组合成一个完整的Object。

调用ossClient.completeMultipartUpload完成分片上传的示例代码如下:

  1. Collections.sort(partETags, new Comparator<PartETag>() {
  2. @Override
  3. public int compare(PartETag p1, PartETag p2) {
  4. return p1.getPartNumber() - p2.getPartNumber();
  5. }
  6. });
  7. CompleteMultipartUploadRequest completeMultipartUploadRequest =
  8. new CompleteMultipartUploadRequest(bucketName, key, uploadId, partETags);
  9. ossClient.completeMultipartUpload(completeMultipartUploadRequest);

注意:

  • 上面代码中的 partETags 就是进行分片上传中保存的partETag的列表,它必须是按PartNumber升序排列。
  • 分片可以是不连续的。

步骤3:取消分片上传事件

您可以调用abortMultipartUpload接口,根据Upload ID中止对应的Multipart Upload事件。当一个Multipart Upload事件被中止后,就不能再使用这个Upload ID做任何操作,已经上传的Part数据也会被删除。

调用ossClient.abortMultipartUpload取消分片上传事件的示例代码如下:

  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>", "<yourKey>", "<uploadId>");
  11. ossClient.abortMultipartUpload(abortMultipartUploadRequest);
  12. // 关闭client
  13. ossClient.shutdown();

获取已上传的分片

获取上传的分片可以罗列出指定Upload ID所属的所有已经上传成功的分片。可以调用ossClient.listParts获取某个上传事件所有已上传分片。listParts的可设置的参数如下:

参数 描述 如何设置值
UploadId Upload Id,initiateMultipartUpload返回的结果获取。 ListPartsRequest.setUploadId(String uploadId)
MaxParts OSS响应中的最大Part数目,即分页时每一页中Part数目。 ListPartsRequest.setMaxParts(int maxParts)
PartNumberMarker 指定List的起始位置,只有Part Number数目大于该参数的Part会被列出。 ListPartsRequest.setPartNumberMarker(Integer partNumberMarker)

简单列举

  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>", "<yourKey>", "<uploadId>");
  10. PartListing partListing = ossClient.listParts(listPartsRequest);
  11. for (PartSummary part : partListing.getParts()) {
  12. // 分片号,上传时候指定
  13. part.getPartNumber();
  14. // 分片数据大小
  15. part.getSize();
  16. // Part的ETag
  17. part.getETag();
  18. // Part的最后修改上传
  19. part.getLastModified();
  20. }
  21. // 关闭client
  22. ossClient.shutdown();

提示:

  • 默认情况下,如果存储空间中的分片上传事件的数量大于1000,则只会返回1000个Multipart Upload信息,且返回结果中 IsTruncated 为false,并返回 NextPartNumberMarker作为下此读取的起点。
  • 如果没有一次性获取所有的上传分片,可以采用分页列举的方式。

获取所有已上传分片

默认情况下,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>", "<yourKey>", "<uploadId>");
  11. do {
  12. partListing = ossClient.listParts(listPartsRequest);
  13. for (PartSummary part : partListing.getParts()) {
  14. // 分片号,上传时候指定
  15. part.getPartNumber();
  16. // 分片数据大小
  17. part.getSize();
  18. // Part的ETag
  19. part.getETag();
  20. // Part的最后修改上传
  21. part.getLastModified();
  22. }
  23. listPartsRequest.setPartNumberMarker(partListing.getNextPartNumberMarker());
  24. } while (partListing.isTruncated());
  25. // 关闭client
  26. 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>", "<yourKey>", "<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. // Part的ETag
  21. part.getETag();
  22. // Part的最后修改上传
  23. part.getLastModified();
  24. }
  25. listPartsRequest.setPartNumberMarker(partListing.getNextPartNumberMarker());
  26. } while (partListing.isTruncated());
  27. // 关闭client
  28. ossClient.shutdown();

获取存储空间内所有分片上传事件

列举分片上传事件可以罗列出所有执行中的分片上传事件,即已经初始化的尚未Complete或者Abort的分片上传事件。列举分片上传的可设置的参数如下:

参数 作用 如何设置值
Prefix 限定返回的文件名(object)必须以Prefix作为前缀。注意使用Prefix查询时,返回的文件名(Object)中仍会包含Prefix。 ListMultipartUploadsRequest.setPrefix(String prefix)
Delimiter 用于对Object名字进行分组的字符。所有名字包含指定的前缀且第一次出现delimiter字符之间的object作为一组元素。 ListMultipartUploadsRequest.setDelimiter(String delimiter)
MaxUploads 限定此次返回分片上传事件的最大数目,默认为1000,MaxUploads取值不能大于1000。 ListMultipartUploadsRequest.setMaxUploads(Integer maxUploads)
KeyMarker 所有Object名字的字典序大于KeyMarker参数值的Multipart事件。可以与UploadIdMarker参数一同使用来指定返回结果的起始位置。 ListMultipartUploadsRequest.setKeyMarker(String keyMarker)
UploadIdMarker 与KeyMarker参数一同使用来指定返回结果的起始位置。 如果KeyMarker参数未设置,则OSS忽略UploadIdMarker参数。 如果KeyMarker参数被设置,查询结果中包含:所有Object名字的字典序大于KeyMarker参数值和Object名字等于KeyMarker参数值且Upload ID比UploadIdMarker参数值大的分片上传事件。 ListMultipartUploadsRequest.setUploadIdMarker(String uploadIdMarker)

调用ossClient.listMultipartUploads获取存储空间内分片上传事件。

简单列举分片上传事件

  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. ListMultipartUploadsRequest listMultipartUploadsRequest = new ListMultipartUploadsRequest(bucketName);
  11. MultipartUploadListing multipartUploadListing = ossClient.listMultipartUploads(listMultipartUploadsRequest);
  12. for (MultipartUpload multipartUpload : multipartUploadListing.getMultipartUploads()) {
  13. // Upload Id
  14. multipartUpload.getUploadId();
  15. // Key
  16. multipartUpload.getKey();
  17. // Date of initiate multipart upload
  18. multipartUpload.getInitiated();
  19. }
  20. // 关闭client
  21. ossClient.shutdown();

提示:

  • 默认情况下,如果存储空间中的分片上传事件的数量大于1000,则只会返回1000个文件, 且返回结果中 IsTruncated 为 false,返回 NextKeyMarker 和 NextUploadIdMarker 作为下次读取的起点。
  • 如果没有一次性获取所有的上传事件,可以采用分页列举的方式。

列举全部上传事件

  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. // Upload Id
  16. multipartUpload.getUploadId();
  17. // Key
  18. multipartUpload.getKey();
  19. // Date of initiate multipart upload
  20. multipartUpload.getInitiated();
  21. }
  22. listMultipartUploadsRequest.setKeyMarker(multipartUploadListing.getNextKeyMarker());
  23. listMultipartUploadsRequest.setUploadIdMarker(multipartUploadListing.getNextUploadIdMarker());
  24. } while (multipartUploadListing.isTruncated());
  25. // 关闭client
  26. ossClient.shutdown();

分页列举全部上传事件

默认情况下,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. // 每个页中事件数目
  13. listMultipartUploadsRequest.setMaxUploads(50);
  14. do {
  15. multipartUploadListing = ossClient.listMultipartUploads(listMultipartUploadsRequest);
  16. for (MultipartUpload multipartUpload : multipartUploadListing.getMultipartUploads()) {
  17. // Upload Id
  18. multipartUpload.getUploadId();
  19. // Key
  20. multipartUpload.getKey();
  21. // Date of initiate multipart upload
  22. multipartUpload.getInitiated();
  23. }
  24. listMultipartUploadsRequest.setKeyMarker(multipartUploadListing.getNextKeyMarker());
  25. listMultipartUploadsRequest.setUploadIdMarker(multipartUploadListing.getNextUploadIdMarker());
  26. } while (multipartUploadListing.isTruncated());
  27. // 关闭client
  28. ossClient.shutdown();

Post上传

OSS Java SDK目前暂不支持Post上传Object,示例提供了PostObject的示例程序,您可以直接使用或再示例基础上修改,请参考PostObjectSample。如果您对Put Object有疑惑请参考OSS Post Object的API,请参考PostObject。让您在修改或实现Post Object过程中有问题或疑问,请参考JAVA模拟PostObject表单上传OSS

上传进度条

OSS Java SDK支持进度条功能,指示上传/下载的进度。下面的代码以ossClient.putObject为例,说明进度条功能的使用。

提示:上传进度条的完整代码请参考:GitHub

  1. static class PutObjectProgressListener implements ProgressListener {
  2. private long bytesWritten = 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 upload......");
  12. break;
  13. case REQUEST_CONTENT_LENGTH_EVENT:
  14. this.totalBytes = bytes;
  15. System.out.println(this.totalBytes + " bytes in total will be uploaded to OSS");
  16. break;
  17. case REQUEST_BYTE_TRANSFER_EVENT:
  18. this.bytesWritten += bytes;
  19. if (this.totalBytes != -1) {
  20. int percent = (int)(this.bytesWritten * 100.0 / this.totalBytes);
  21. System.out.println(bytes + " bytes have been written at this time, upload progress: " + percent + "%(" + this.bytesWritten + "/" + this.totalBytes + ")");
  22. } else {
  23. System.out.println(bytes + " bytes have been written at this time, upload ratio: unknown" + "(" + this.bytesWritten + "/...)");
  24. }
  25. break;
  26. case TRANSFER_COMPLETED_EVENT:
  27. this.succeed = true;
  28. System.out.println("Succeed to upload, " + this.bytesWritten + " bytes have been transferred in total");
  29. break;
  30. case TRANSFER_FAILED_EVENT:
  31. System.out.println("Failed to upload, " + this.bytesWritten + " bytes have been transferred");
  32. break;
  33. default:
  34. break;
  35. }
  36. }
  37. public boolean isSucceed() {
  38. return succeed;
  39. }
  40. }
  41. public static void main(String[] args) {
  42. // endpoint以杭州为例,其它region请按实际情况填写
  43. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
  44. // 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号
  45. String accessKeyId = "<yourAccessKeyId>";
  46. String accessKeySecret = "<yourAccessKeySecret>";
  47. String bucketName = "<yourBucketName>";
  48. String key = "<yourkey>";
  49. // 创建OSSClient实例
  50. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  51. try {
  52. // 带进度条的上传
  53. ossClient.putObject(new PutObjectRequest(bucketName, key, new FileInputStream("<yourLocalFile>")).
  54. <PutObjectRequest>withProgressListener(new PutObjectProgressListener()));
  55. } catch (Exception e) {
  56. e.printStackTrace();
  57. }
  58. ossClient.shutdown();
  59. }

提示:

  • putObject/getObject/uploadPart都支持进度条功能。
  • uploadFile/downloadFile不支持进度条功能。

上传回调

OSS在上传文件完成的时候可以提供回调(Callback)给应用服务器。用户只需要在发送给OSS的请求中携带相应的Callback参数,即能实现回调。现在支持Callback的接口有:PutObject、PostObject、CompleteMultipartUpload。

上传回调的一种典型应用场景是与授权第三方上传同时使用,客户端在上传文件到OSS的时候指定到服务器端的回调,当客户端的上传任务在OSS执行完毕之后,OSS会向应用服务器端主动发起HTTP请求进行回调,这样服务器端就可以及时得到上传完成的通知从而可以完成诸如数据库修改等操作,当回调请求接收到服务器端的响应之后OSS才会将状态返回给客户端。

您想了解上传回调的更详细信息,请参考上传回调。下面以PutObject为例说明上传回调的用法。

提示: 上传回调的完整代码请参考:GitHub

  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. // 您的回调服务器地址,如http://oss-demo.aliyuncs.com或http://127.0.0.1:9090
  8. String callbackUrl = "<yourCallbackServerUrl>";
  9. // 创建OSSClient实例
  10. OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
  11. String content = "Hello OSS";
  12. PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, "key",new ByteArrayInputStream(content.getBytes()));
  13. // 上传回调参数
  14. Callback callback = new Callback();
  15. callback.setCallbackUrl(callbackUrl);
  16. callback.setCallbackHost("oss-cn-hangzhou.aliyuncs.com");
  17. callback.setCallbackBody("{\\\"mimeType\\\":${mimeType},\\\"size\\\":${size}}");
  18. callback.setCallbackBodyType(CallbackBodyType.JSON);
  19. callback.addCallbackVar("x:var1", "value1");
  20. callback.addCallbackVar("x:var2", "value2");
  21. putObjectRequest.setCallback(callback);
  22. PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
  23. // 读取上传回调返回的消息内容
  24. byte[] buffer = new byte[1024];
  25. putObjectResult.getCallbackResponseBody().read(buffer);
  26. // 一定要close,否则会造成连接资源泄漏
  27. putObjectResult.getCallbackResponseBody().close();
  28. // 关闭client
  29. ossClient.shutdown();

相关文档

本文导读目录