一、什么是OSS存储
阿里云对象存储OSS(Object Storage Service)是一款海量、安全、低成本、高可靠的云存储服务,可提供99.9999999999%(12个9)的数据持久性,99.995%的数据可用性。多种存储类型供选择,全面优化存储成本, 可以使用阿里云提供的 API、SDK 接口或者 OSS 迁移工具轻松地将海量数据移入或移出阿里云 OSS。
二、OSS工作原理及基本概念
1、工作原理
数据以对象(Object)的形式存储在OSS的存储空间(Bucket )中。如果要使用OSS存储数据,需要先创建Bucket,并指定Bucket的地域、访问权限、存储类型等属性。创建Bucket后,您可以将数据以Object的形式上传到Bucket,并指定Object的文件名(Key)作为其唯一标识。
OSS以HTTP RESTful API的形式对外提供服务,访问不同地域需要不同的访问域名(Endpoint)。当您请求访问OSS时,OSS通过使用访问密钥(AccessKey ID和AccessKey Secret)对称加密的方法来验证某个请求的发送者身份。
Object操作在OSS上具有原子性和强一致性。
2、存储空间
存储空间是用户用于存储对象(Object)的容器,所有的对象都必须隶属于某个存储空间。存储空间具有各种配置属性,包括地域、访问权限、存储类型等。用户可以根据实际需求,创建不同类型的存储空间来存储不同的数据。
-
同一阿里云账号在同一地域内创建的存储空间总数不能超过100个。
-
存储空间名称在OSS范围内必须全局唯一。有关存储空间的命名规范,请参见存储空间命名。
-
Bucket名称在OSS范围内必须全局唯一。
-
只能包括小写字母、数字和短划线(-)。
-
必须以小写字母或者数字开头和结尾。
-
长度为3~63个字符。
命名示例
Bucket名称的正确示例如下:
-
examplebucket1
-
test-bucket-2021
-
aliyun-oss-bucket
Bucket名称的错误示例以及错误的原因如下:
Examplebucket1(包含了大写字母)
test_bucket_2021(包含了下划线)
aliyun-oss-bucket-(结尾包含了短划线)
3、对象
对象是OSS存储数据的基本单元,也被称为OSS的文件。和传统的文件系统不同,对象没有文件目录层级结构的关系。对象由元信息(Object Meta),用户数据(Data)和文件名(Key)组成,并且由存储空间内部唯一的Key来标识。对象元信息是一组键值对,表示了对象的一些属性,比如最后修改时间、大小等信息,同时用户也可以在元信息中存储一些自定义的信息。对象的生命周期是从上传成功到被删除为止。在整个生命周期内,除通过追加方式上传的Object可以通过继续追加上传写入数据外,其他方式上传的Object内容无法编辑,您可以通过重复上传同名的对象来覆盖之前的对象。
对象的命名规范如下:
-
使用UTF-8编码。
-
长度必须在1~1023字符之间。
-
不能以正斜线(/)或者反斜线(\)开头。
说明:对象名称需要区分大小写。如无特殊说明,本文档中的对象、文件称谓等同于Object。
4、对象名称
在各语言SDK中,ObjectKey、Key以及ObjectName是同一概念,均表示对Object执行相关操作时需要填写的Object名称。例如向某一存储空间上传Object时,ObjectKey表示上传的Object所在存储空间的完整名称,即包含文件后缀在内的完整路径,如填写为abc/efg/123.jpg。
5、地域
Region表示OSS的数据中心所在物理位置。用户可以根据费用、请求来源等选择合适的地域创建Bucket。一般来说,距离用户更近的Region访问速度更快。
6、访问域名
Endpoint表示OSS对外服务的访问域名。OSS以HTTP RESTful API的形式对外提供服务,当访问不同的Region的时候,需要不同的域名。通过内网和外网访问同一个Region所需要的Endpoint也是不同的。例如杭州Region的外网Endpoint是oss-cn-hangzhou.aliyuncs.com,内网Endpoint是oss-cn-hangzhou-internal.aliyuncs.com。
7、用户ID
AccessKey简称AK,指的是访问身份验证中用到的AccessKey ID和AccessKey Secret。OSS通过使用AccessKey ID和AccessKey Secret对称加密的方法来验证某个请求的发送者身份。AccessKey ID用于标识用户。
8、访问密钥
AccessKey简称AK,指的是访问身份验证中用到的AccessKey ID和AccessKey Secret。OSS通过使用AccessKey ID和AccessKey Secret对称加密的方法来验证某个请求的发送者身份。AccessKey Secret是用户用于加密签名字符串和OSS用来验证签名字符串的密钥,必须保密。
AccessKey包含以下三种:
-
Bucket的拥有者申请的AccessKey。
-
被Bucket的拥有者通过RAM授权给第三方请求者的AccessKey。
-
被Bucket的拥有者通过STS授权给第三方请求者的AccessKey。
强一致性
Object操作在OSS上具有原子性,操作要么成功要么失败,不会存在有中间状态的Object。OSS保证用户一旦上传完成之后读到的Object是完整的,OSS不会返回给用户一个部分上传成功的Object。
Object操作在OSS同样具有强一致性,用户一旦收到了一个上传(PUT)成功的响应,该上传的Object就已经立即可读,且数据已经冗余写入到多个设备中。不存在上传的中间状态,即不会出现read-after-write却无法读取到数据的情况。删除操作也类似,即用户成功删除指定的Object后,该Object立即变为不存在。
9、存储模式
对象存储OSS提供标准、低频访问、归档、冷归档、深度冷归档多种存储类型,全面覆盖从热到冷的各种数据存储场景。
1、标准存储(Standard):提供高可靠、高可用、高性能的对象存储服务,能够支持频繁的数据访问。适用于各种社交、分享类的图片、音视频应用、大型网站、大数据分析等业务场景。提供标准存储-本地冗余(LRS)和标准存储-同城冗余(ZRS)两种数据冗余存储方式。
2、低频访问存储(Infrequent Access):提供高持久性、较低存储成本的对象存储服务。有最小计量单位(64 KB)和最低存储时间(30天)的要求。支持数据实时访问,访问数据时会产生数据取回费用,适用于较低访问频率(平均每月访问频率1到2次)的业务场景。提供低频访问-本地冗余(LRS)和低频访问-同城冗余(ZRS)两种数据冗余存储方式。
3、归档存储(Archive):提供高持久性、极低存储成本的对象存储服务。有最小计量单位(64 KB)和最低存储时间(60天)要求。归档存储数据支持解冻(约1分钟)后访问或直接访问。解冻后访问会产生归档存储数据取回容量费用,直接访问会产生归档直读数据取回容量费用。归档存储适用于数据长期保存的业务场景,例如档案数据、医疗影像、科学资料、影视素材等。提供归档存储-本地冗余(LRS)和归档存储-同城冗余(ZRS)两种数据冗余存储方式。
4、冷归档存储(Cold Archive): 提供高持久性、比归档存储的存储成本更低的对象存储服务。有最小计量单位(64 KB)和最低存储时间(180天)的要求。数据需解冻后访问,解冻时间根据数据大小和选择的解冻模式决定,解冻会产生数据取回费用以及取回请求费用。适用于需要超长时间存放的冷数据,例如因合规要求需要长期留存的数据、大数据及人工智能领域长期积累的原始数据、影视行业长期留存的媒体资源、在线教育行业的归档视频等业务场景。
5、深冷归档存储(Deep Cold Archive):提供高持久性、比冷归档存储成本更低的对象存储服务。有最小计量单位(64 KB)和最低存储时间(180天)的要求。数据需解冻后访问,解冻时间根据数据大小和选择的解冻模式决定,解冻会产生数据取回费用以及取回请求费用。适用于需要超长时间存放的极冷数据,例如大数据及人工智能领域的原始数据的长期积累留存、媒体数据的长期保留、法规和合规性存档、磁带替换等业务场景。
OSS 具有与平台无关的 RESTful API 接口,可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
10、应用场景
10.1、图片和音视频等应用的海量存储
OSS可用于图片、音视频、日志等海量文件的存储。各种终端设备、Web网站程序、移动应用可以直接向OSS写入或读取数据。OSS支持流式写入和文件写入两种方式。
10.2、网页或者移动应用的静态和动态资源分离
利用海量互联网带宽,OSS可以实现海量数据的互联网并发下载。OSS提供原生的传输加速功能,支持上传加速、下载加速,提升跨国、跨洋数据上传、下载的体验。同时,OSS也可以结合CDN产品,提供静态内容存储、分发到边缘节点的解决方案,利用CDN边缘节点缓存的数据,提升同一个文件被同一地区客户大量重复并发下载的体验。
10.3、云端数据处理
上传文件到OSS后,可以配合智能媒体管理服务和图片处理服务进行云端的数据处理。
11、产品计费:
11.1、计费方式:
对象存储OSS支持以下计费方式。
-
按量付费:所有计费项默认采用按量付费。按照各计费项的实际用量结算费用,先使用,后付费,适用于业务用量经常有变化的场景。
计费规则:资源按照实际用量结算,在每个结算周期生成账单并从账户中扣除相应费用。
适用场景:
按量计费主要适用于以下业务场景:
业务用量经常有变化的场景。
资源使用有临时性和突发性。
-
资源包:针对部分常用计费项支持专用的资源包。预先购买针对不同的计费项推出的优惠资源包,在费用结算时,优先从资源包抵扣用量,先购买,后抵扣,适用于业务用量相对稳定的场景。
选购建议:
根据使用场景选择资源包类型
根据账单的计费项选择资源包类型
如果您已有OSS账单,建议您根据明细账单里的计费项选择您要购买的资源包类型。例如,计费项为标准存储(本地冗余)容量,那么您可以购买标准-本地冗余存储包抵扣该费用。
根据账单的用量选择资源包规格
如果已有OSS账单,建议根据明细账单里的用量选择您要购买的资源包规格。例如,标准存储(本地冗余)容量每小时的用量为40 GB,那么可以购买40 GB的标准-本地冗余存储包抵扣该费用。
购买后仍然按小时扣费的排查方法
1、在明细账单页面,查看计费项的类型、用量、消费时间。
2、在资源包列表页面,查看生效的资源包的类型、总量、生效时间。
3、对比计费项和资源包。
11.2、抵扣限制:
-
OSS资源包仅支持抵扣当前阿里云账号下产生的费用,不支持跨账号抵扣。
-
OSS资源包为OSS服务专用资源包,不支持跨产品抵扣。
-
OSS资源包仅支持抵扣资源包购买后产生的费用,不支持抵扣资源包购买前产生的费用。
-
一种类型的资源包只能抵扣使用该资源包对应计费项产生的费用,不能抵扣所有费用。
-
OSS指定地域的资源包仅支持抵扣对应地域该资源包对应计费项产生的费用,中国内地通用资源包支持跨地域抵扣多个中国内地各地域该资源包对应计费项产生的费用。
11.3、抵扣方式:
-
预留空间:针对有地域属性Bucket产生的标准存储(本地冗余)容量费用以及ECS快照存储费用的预付费产品。预先购买预留空间,在费用结算时,优先从预留空间抵扣用量,先购买,后抵扣。无地域属性预留空间:针对无地域属性Bucket产生的标准存储(本地冗余)容量费用的预付费产品。预先购买无地域属性的预留空间,在费用结算时,优先从无地域属性预留空间抵扣用量,先购买,后抵扣。
-
存储容量单位包SCU:针对存储费用支持SCU。SCU除了用于抵扣OSS的存储费用,还可用于抵扣多种云存储产品存储容量费用。
12、Oss与文件系统的对比
从上述表格得知,不建议将OSS映射为文件系统。如果结合您的业务场景需要将OSS挂载为文件系统,建议只执行写入文件、删除文件、读取文件操作。使用OSS应该充分发挥其优点,即海量数据处理能力,优先用来存储海量的非结构化数据,例如图片、视频、文档等。
13、数据备份和容灾
-
备份存储空间
针对存放在对象存储OSS上的数据,阿里云提供多种数据备份方式,以满足不同场景的备份需求。本文介绍备份OSS数据的几种主要方式。
-
通过定时备份功能进行备份
云备份(Cloud Backup)可创建备份计划,并按计划将您OSS内的数据备份到云备份(Cloud Backup)中,当您的数据因误修改、误删除等原因丢失时,可及时恢复。您也可以使用云备份(Cloud Backup)长期、低成本地保存OSS的历史数据
-
通过跨区域复制功能进行备份
跨区域复制是跨不同OSS数据中心(地域)的存储空间(Bucket)自动、异步(近实时)复制文件,它会将文件的创建、更新和删除等操作从源存储空间复制到不同区域的目标存储空间。
-
通过在线迁移服务进行备份
阿里云在线迁移服务是阿里云提供的存储产品数据通道。使用在线迁移服务,您可以将第三方数据轻松迁移至OSS,也可以在OSS之间进行灵活的数据迁移。
-
通过ossimport工具进行备份
ossimport是一款将数据迁移至OSS的工具。您可以将ossimport部署在本地服务器或云上ECS实例内,轻松将您本地或其它云存储的数据迁移到OSS。
13.1、数据库备份到OSS
对象存储OSS
对象存储OSS提供了标准类型存储,作为移动应用、大型网站、图片分享或热点音视频的主要存储方式,也提供了成本更低、存储期限更长的低频访问类型存储和归档类型存储,作为不经常访问数据的备份和归档。对象存储OSS非常适合作为数据库备份的存储介质。
13.2、数据库备份DBS
数据库备份DBS是为数据库提供连续数据保护、低成本的备份服务。它可以为多种环境的数据提供强有力的保护,包括企业数据中心、其他云厂商及公共云。数据库备份提供数据备份和操作恢复的整体方案,具备实时增量备份、精确到秒级的数据恢复能力。
13.3、应用场景
数据库备份到OSS的方案应用场景如下:
-
阿里云RDS或阿里云ECS自建数据库在OSS上备份或长期归档
-
自建IDC数据备份上云
-
其他云数据库在阿里云OSS上做多云备份
-
数据库做异地备份灾备
方案优势
-
支持全量或实时增量备份
-
秒级RPO:日志内存实时捕获,CDP实时备份,RPO达到秒级。
-
无锁并发:全程无锁备份、并发备份、数据拉取自适应分片。
-
精准恢复:恢复对象精准匹配,单表恢复,从而大幅降低RTO。
-
灵活恢复:提供可恢复日历及时间轴选择,实现任意时间点恢复。
-
-
数据强安全高可靠
-
异地灾备:利用OSS的跨区域复制功能,做备份数据的异地灾备,提升数据保护级别。
-
数据传输加密:在传输过程中进行SSL加密,保障数据安全性。
-
数据存储加密:对备份到OSS的数据进行加密存储,保障数据隐私性。
-
随时验证:随时验证数据库备份的有效性。
-
-
低成本
-
按需付费:OSS存储空间按需付费,避免一次性投入大量资产。
-
自动存储分级:OSS提供标准、低频、归档多种类型,全面优化存储成本。
-
弹性扩展:OSS存储容量弹性扩展,无缝支撑企业在不同发展阶段的性能要求。
-
-
支持多环境多数据源
-
支持MySQL、Oracle、SQL Server、MongoDB多种数据库。
-
支持IDC、第三方云数据库、阿里云RDS、阿里云ECS自建数据库。
-
14、数据迁移
14.1、使用数据复制功能迁移同账号下的OSS数据
-
不同地域Bucket之间的数据迁移
例如,您需要将华北2(北京)地域的源Bucket A的所有数据迁移到华东1(杭州)的目标Bucket B,具体步骤如下
-
登录OSS管理控制台。
-
在左侧导航栏,单击Bucket 列表,然后单击Bucket A。
-
在左侧导航栏,选择数据管理 > 跨区域复制。
-
在跨区域复制页签,单击跨区域复制。
-
在跨区域复制面板配置以下参数。
-
点击确定。此时,跨区域复制页签将显示数据迁移进度。
参数 说明及示例值 源 Bucket 显示Bucket A所在地域华北2(北京)和Bucket A名称。 目标Bucket 选择华东1(杭州)和Bucket B。 数据复制对象 选择全部文件进行同步。 数据复制策略 选择增/改 同步。OSS会将源Bucket的增、改操作同步到目标Bucket上。 复制历史数据 选择复制。
-
-
相同地域Bucket之间的数据迁移
例如,您需要将华北2(北京)地域的源Bucket C的所有数据迁移到相同地域的目标Bucket D,具体步骤如下:
-
登录OSS管理控制台。
-
在左侧导航栏,单击Bucket 列表,然后单击Bucket C。
-
在左侧导航栏,选择数据管理 > 同区域复制。
-
在同区域复制页签,单击同区域复制。
-
在同区域复制面板,按如下说明配置各项参数。
-
l 单击确定。此时,同区域复制页签将显示数据迁移进度。
-
参数 | 说明及示例值 |
---|---|
源 Bucket | 显示Bucket C所在地域华北2(北京)和Bucket C的名称。 |
目标Bucket | 选择华北2(北京)和Bucket D。 |
数据复制对象 | 选择全部文件进行同步。 |
数据复制策略 | 选择增/改同步。OSS会将源Bucket的增、改操作同步到目标Bucket上。 |
复制历史数据 | 选择复制。 |
KMS 加密目标对象复制 | 选择不复制。 |
14.2、使用在线迁移服务跨账号迁移OSS数据
例如,您需要以外网Endpoint的方式,将阿里云账号A下华东2(上海)地域下的OSS Bucket A的数据迁移至阿里云账号B华东1(杭州)地域的Bucket B。具体步骤如下
1、 创建源地址
-
登录阿里云数据在线迁移控制台。
-
在左侧导航栏,选择在线迁移服务 > 数据地址,然后单击右上角的创建数据地址。
-
在创建数据地址面板,按如下说明配置各项参数。
2、 创建目的地址
-
在左侧导航栏,选择在线迁移服务 > 数据地址,然后单击右上角的创建数据地址。
-
在创建数据地址面板,按如下说明配置如各项参数。
参数 | 说明和示例值 |
---|---|
数据类型 | 选择OSS。 |
数据所在区域 | 选择华东1(杭州)。 |
数据名称 | 输入migrationtask2。 |
开通并使用传输加速 | 不勾选。 |
OSS Endpoint | 选择https://oss-cn-hangzhou.aliyuncs.com。 |
AccessKey Id | 输入RAM用户B的AccessKey ID。 |
AccessKey Secret | 输入RAM用户B的AccessKey Secret。 |
OSS Bucket | 选择Bucket B。 |
OSS Prefix | 不填写,迁移全部。 |
3、 创建迁移任务
-
选择在线迁移服务 > 迁移任务,然后单击创建迁移任务。
-
在创建迁移任务面板,阅读迁移服务条款协议,选中我理解如上条款,并开通数据迁移服务,然后单击下一步。
-
在弹出的费用提示对话框,单击确认,继续创建。
-
在任务配置页签,设置以下参数,其他参数保留默认值,然后单击下一步
-
在性能调优页签的数据预估区域,填写待迁移存储量和待迁移文件个数。
-
在性能调优页签的流量控制区域,设置限流时间段和最大流量,然后单击添加。
-
单击创建
参数 | 说明和示例值 |
---|---|
任务名称 | 输入task2。 |
源地址 | 选择已创建的源地址[oss]migrationtask1。 |
目的地址 | 选择已创建的目的地址[oss]migrationtask2。 |
迁移方式 | 选择全量迁移。 |
14.3、跨账号同地域迁移OSS数据
例如,您可以通过内网Endpoint的方式,将阿里云账号A下华东2(上海)地域下的OSS Bucket A的数据迁移至阿里云账号B相同地域的Bucket B。具体步骤如下:
1、创建源地址。
-
登录阿里云数据在线迁移控制台。
-
在左侧导航栏,选择在线迁移服务 > 数据地址,然后单击右上角的创建数据地址。
-
在创建数据地址面板,按如下说明配置如各项参数。
2、创建目的地址。
-
在左侧导航栏,选择在线迁移服务 > 数据地址,然后单击右上角的创建数据地址。
-
在创建数据地址面板,按如下说明配置如各项参数。
参数 说明和示例值 数据类型 选择OSS。 数据所在区域 选择华东2(上海)。 数据名称 输入migrationtask2。 开通并使用传输加速 不勾选。 OSS Endpoint 选择https://oss-cn-shanghai-internal.aliyuncs.com。 AccessKey Id 输入RAM用户B的AccessKey ID。 AccessKey Secret 输入RAM用户B的AccessKey Secret。 OSS Bucket 选择Bucket B。 OSS Prefix 不填写,迁移全部。
3、创建迁移任务
-
选择在线迁移服务 > 迁移任务,然后单击创建迁移任务。
-
在创建迁移任务面板,阅读迁移服务条款协议,选中我理解如上条款,并开通数据迁移服务,然后单击下一步
-
在弹出的费用提示对话框,单击确认,继续创建。
-
在任务配置页签,设置以下参数,其他参数保留默认值,然后单击下一步。
-
在性能调优页签的数据预估区域,填写待迁移存储量和待迁移文件个数。
-
在性能调优页签的流量控制区域,设置限流时间段和最大流量,然后单击添加。
-
单击创建
参数 | 说明和示例值 |
---|---|
任务名称 | 输入task2。 |
源地址 | 选择已创建的源地址[oss]migrationtask1。 |
目的地址 | 选择已创建的目的地址[oss]migrationtask2。 |
迁移方式 | 选择全量迁移。 |
三、阿里云OSS特性和优势
1、阿里云OSS特性
1.1. 高可靠性
阿里云OSS基于阿里云自研的分布式系统架构,能自动将数据复制到不同的存储节点,使其具备高可靠性。即使某个存储节点发生故障,阿里云OSS也能自动切换到其他存储节点,保证数据的完整性。
1.2. 数据保密性
阿里云OSS支持多种加密算法,能将用户数据进行加密存储,确保数据的保密性。同时,它还支持身份认证和权限控制功能,可以精确地控制用户对数据的访问权限。
1.3. 高扩展性
阿里云OSS具备高扩展性,用户可以根据自己的需求灵活地扩展存储容量和带宽。它采用了分布式架构和负载均衡技术,能够自动地进行数据水平扩展,保证了高并发负载下的系统稳定性。
1.4. 多种数据处理能力
阿里云OSS具备多种数据处理能力,支持图片、视频、音频等多种格式的数据,可以进行图片缩略图、音视频转码等操作,满足用户对数据的不同需求。
2、阿里云OSS的优势
2.1. 低成本
阿里云OSS的存储费用低廉,按用户实际使用量计费,无需预存款或定期付费,能够节省用户大量的成本。
2.2. 高性能
阿里云OSS的访问速度快,可以为用户提供高性能的服务。它支持全球加速,能够将数据缓存在全球各地,实现全球负载均衡,提升访问速度。
2.3. 易于使用
阿里云OSS的接口简单易用,用户可以轻松地进行数据上传、下载、删除等操作,它还提供了完善的开发工具包和SDK,方便用户快速进行开发和集成。
2.4. 可靠性高
阿里云OSS具备高可靠性,能够自动实现数据备份和容灾,系统故障自动转移,确保数据的安全和完整性。
总之,阿里云OSS作为云端对象存储服务,具备高可靠性、高性能、低成本和易于使用的特点,是企业和个人存储海量数据的最佳选择。
四、使用阿里云OSS控制台管理OSS
1、创建桶
打开阿里云oss控制台 点击立即创建 然后创建想要的桶
2、上传文件到OSS
创建桶以后,就可以上传到OSS了。打开桶详情,点击上传:
选择:私有,点击:扫描文件,就可以上传文件了。
3、从OSS下载文件
点击到桶详情,看到文件,直接点击下载即可。
五、代码对接阿里云OSS API
1、创建并授权RAM用户
为了保护的阿里云账号(主账号)安全,在完成阿里云账号的基本设置后,建议创建一个RAM用户,并授予该RAM用户管理阿里云账号下所有资源的权限。
阿里云账号相当于Linux操作系统的root用户,具有一个账号内的全部资源管理权限。如果日常工作中一直使用阿里云账号,不但有误操作的风险,而且还有账号被盗而导致的数据泄露、数据被删除等风险。因此,在日常工作中,建议您使用具有管理员权限的RAM用户代替阿里云账号。
1.1 什么是RAM用户
RAM用户是RAM的一种实体身份类型,有确定的身份ID和身份凭证,它通常与某个确定的人或应用程序一一对应。RAM用户具备以下特点:
-
RAM用户由阿里云账号(主账号)或具有管理员权限的其他RAM用户、RAM角色创建,创建成功后,归属于该阿里云账号,它不是独立的阿里云账号。
-
RAM用户不拥有资源,不能独立计量计费,由所属的阿里云账号统一付费。
-
RAM用户必须在获得授权后,才能登录控制台或使用API访问阿里云账号下的资源。
-
RAM用户拥有独立的登录密码或访问密钥。一个阿里云账号下可以创建多个RAM用户,对应企业内的员工、系统或应用程序。
可以创建RAM用户并为其授权,实现不同RAM用户拥有不同资源访问权限的目的。当您的企业存在多用户协同访问资源的场景时,使用RAM可以按需为用户分配最小权限,避免多用户共享阿里云账号密码或访问密钥,从而降低企业的安全风险。
1.2、创建RAM用户的AccessKey
-
登录RAM控制台
-
在左侧导航栏 选择身份管理>用户
-
在用户页面,单击目标RAM用户名称
-
在用户AccessKey区域,单击创建AccessKey
-
根据界面提示完成安全验证
-
在创建AccessKey对话框 查看AccessKey ID和 AccessKey secret
导入依赖
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibabacloud-sts20150401</artifactId>
<version>3.1.0</version>
</dependency>
1.3、使用API创建桶
public class Demo {
public static void main(String[] args) throws Exception {
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
String endpoint = "yourEndpoint";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "yourAccessKeyId";
String accessKeySecret = "yourAccessKeySecret";
// 填写Bucket名称。
String bucketName = "examplebucket";
// 填写资源组ID。如果不填写资源组ID,则创建的Bucket属于默认资源组。
//String rsId = "rg-aek27tc****";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 创建CreateBucketRequest对象。
CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
// 如果创建存储空间的同时需要指定存储类型、存储空间的读写权限、数据容灾类型, 请参考如下代码。
// 此处以设置存储空间的存储类型为标准存储为例介绍。
//createBucketRequest.setStorageClass(StorageClass.Standard);
// 数据容灾类型默认为本地冗余存储,即DataRedundancyType.LRS。如果需要设置数据容灾类型为同城冗余存储,请设置为DataRedundancyType.ZRS。
//createBucketRequest.setDataRedundancyType(DataRedundancyType.ZRS)
// 设置存储空间读写权限为公共读,默认为私有。
//createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
// 在支持资源组的地域创建Bucket时,您可以为Bucket配置资源组。
//createBucketRequest.setResourceGroupId(rsId);
// 创建存储空间。
ossClient.createBucket(createBucketRequest);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
1.4、使用API删除桶
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "yourAccessKeyId";
String accessKeySecret = "yourAccessKeySecret";
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 删除存储空间。
ossClient.deleteBucket(bucketName);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
1.5上传文件
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "yourAccessKeyId";
String accessKeySecret = "yourAccessKeySecret";
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "exampledir/exampleobject.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 填写字符串。
String content = "Hello OSS,你好世界";
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
// 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。
// ObjectMetadata metadata = new ObjectMetadata();
// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
// metadata.setObjectAcl(CannedAccessControlList.Private);
// putObjectRequest.setMetadata(metadata);
// 上传字符串。
PutObjectResult result = ossClient.putObject(putObjectRequest);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
1.6、下载文件到本地
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "yourAccessKeyId";
String accessKeySecret = "yourAccessKeySecret";
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写不包含Bucket名称在内的Object完整路径,例如testfolder/exampleobject.txt。
String objectName = "testfolder/exampleobject.txt";
String pathName = "D:\\localpath\\examplefile.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 下载Object到本地文件,并保存到指定的本地路径中。如果指定的本地文件存在会覆盖,不存在则新建。
// 如果未指定本地路径,则下载后的文件默认保存到示例程序所属项目对应本地路径中。
ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(pathName));
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
1.7删除文件
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "yourAccessKeyId";
String accessKeySecret = "yourAccessKeySecret";
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写文件完整路径。文件完整路径中不能包含Bucket名称。
String objectName = "exampleobject.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 删除文件或目录。如果要删除目录,目录必须为空。
ossClient.deleteObject(bucketName, objectName);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
2、文件上传其他形式
1.1、简单上传:
当需要将本地不超过5 GB大小的文件、图片、视频等资源上传到OSS,且对并发上传性能要求不高的情况下,可以选择简单上传的方式。
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "exampledir/exampleobject.txt";
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
String filePath= "D:\\localpath\\examplefile.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(filePath));
// 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。
// ObjectMetadata metadata = new ObjectMetadata();
// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
// metadata.setObjectAcl(CannedAccessControlList.Private);
// putObjectRequest.setMetadata(metadata);
// 上传文件。
PutObjectResult result = ossClient.putObject(putObjectRequest);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
1.2、分片上传:
在上传大文件(超过5 GB)到OSS的过程中,如果出现网络中断、程序异常退出等问题导致文件上传失败,需要使用分片上传的方式上传大文件。分片上传通过将待上传的大文件分成多个较小的碎片(Part),充分利用网络带宽和服务器资源并发上传多个Part,加快上传完成时间,并在Part上传完成之后调用CompleteMultipartUpload接口将这些Part组合成一个完整的Object。
-
将待上传文件按照一定大小进行分片。
-
使用InitiateMultipartUpload接口初始化一个分片上传任务。
-
使用UploadPart接口上传分片。
文件切分成Part之后,文件顺序是通过上传过程中指定的partNumber
来确定,所以您可以并发上传这些碎片。并发数并非越多越快,请结合自身网络状况和设备负载综合考虑。
如果您希望终止上传任务,可调用AbortMultipartUpload接口,成功上传的Part会一并删除。
-
使用CompleteMultipartUpload接口将Part组合成一个Object。
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = "exampledir/exampleobject.txt";
// 待上传本地文件路径。
String filePath = "D:\\localpath\\examplefile.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
// 创建InitiateMultipartUploadRequest对象。
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);
// 如果需要在初始化分片时设置请求头,请参考以下示例代码。
ObjectMetadata metadata = new ObjectMetadata();
// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
// 指定该Object的网页缓存行为。
// metadata.setCacheControl("no-cache");
// 指定该Object被下载时的名称。
// metadata.setContentDisposition("attachment;filename=oss_MultipartUpload.txt");
// 指定该Object的内容编码格式。
// metadata.setContentEncoding(OSSConstants.DEFAULT_CHARSET_NAME);
// 指定初始化分片上传时是否覆盖同名Object。此处设置为true,表示禁止覆盖同名Object。
// metadata.setHeader("x-oss-forbid-overwrite", "true");
// 指定上传该Object的每个part时使用的服务器端加密方式。
// metadata.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION, ObjectMetadata.KMS_SERVER_SIDE_ENCRYPTION);
// 指定Object的加密算法。如果未指定此选项,表明Object使用AES256加密算法。
// metadata.setHeader(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION, ObjectMetadata.KMS_SERVER_SIDE_ENCRYPTION);
// 指定KMS托管的用户主密钥。
// metadata.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION_KEY_ID, "9468da86-3509-4f8d-a61e-6eab1eac****");
// 指定Object的存储类型。
// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard);
// 指定Object的对象标签,可同时设置多个标签。
// metadata.setHeader(OSSHeaders.OSS_TAGGING, "a:1");
// request.setObjectMetadata(metadata);
// 根据文件自动设置ContentType。如果不设置,ContentType默认值为application/oct-srream。
if (metadata.getContentType() == null) {
metadata.setContentType(Mimetypes.getInstance().getMimetype(new File(filePath), objectName));
}
// 初始化分片。
InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request);
// 返回uploadId。
String uploadId = upresult.getUploadId();
// 根据uploadId执行取消分片上传事件或者列举已上传分片的操作。
// 如果您需要根据您需要uploadId执行取消分片上传事件的操作,您需要在调用InitiateMultipartUpload完成初始化分片之后获取uploadId。
// 如果您需要根据您需要uploadId执行列举已上传分片的操作,您需要在调用InitiateMultipartUpload完成初始化分片之后,且在调用CompleteMultipartUpload完成分片上传之前获取uploadId。
// System.out.println(uploadId);
// partETags是PartETag的集合。PartETag由分片的ETag和分片号组成。
List<PartETag> partETags = new ArrayList<PartETag>();
// 每个分片的大小,用于计算文件有多少个分片。单位为字节。
final long partSize = 1 * 1024 * 1024L; //1 MB。
// 根据上传的数据大小计算分片数。以本地文件为例,说明如何通过File.length()获取上传数据的大小。
final File sampleFile = new File(filePath);
long fileLength = sampleFile.length();
int partCount = (int) (fileLength / partSize);
if (fileLength % partSize != 0) {
partCount++;
}
// 遍历分片上传。
for (int i = 0; i < partCount; i++) {
long startPos = i * partSize;
long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
UploadPartRequest uploadPartRequest = new UploadPartRequest();
uploadPartRequest.setBucketName(bucketName);
uploadPartRequest.setKey(objectName);
uploadPartRequest.setUploadId(uploadId);
// 设置上传的分片流。
// 以本地文件为例说明如何创建FIleInputstream,并通过InputStream.skip()方法跳过指定数据。
InputStream instream = new FileInputStream(sampleFile);
instream.skip(startPos);
uploadPartRequest.setInputStream(instream);
// 设置分片大小。除了最后一个分片没有大小限制,其他的分片最小为100 KB。
uploadPartRequest.setPartSize(curPartSize);
// 设置分片号。每一个上传的分片都有一个分片号,取值范围是1~10000,如果超出此范围,OSS将返回InvalidArgument错误码。
uploadPartRequest.setPartNumber( i + 1);
// 每个分片不需要按顺序上传,甚至可以在不同客户端上传,OSS会按照分片号排序组成完整的文件。
UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
// 每次上传分片之后,OSS的返回结果包含PartETag。PartETag将被保存在partETags中。
partETags.add(uploadPartResult.getPartETag());
}
// 创建CompleteMultipartUploadRequest对象。
// 在执行完成分片上传操作时,需要提供所有有效的partETags。OSS收到提交的partETags后,会逐一验证每个分片的有效性。当所有的数据分片验证通过后,OSS将把这些分片组合成一个完整的文件。
CompleteMultipartUploadRequest completeMultipartUploadRequest =
new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);
// 如果需要在完成分片上传的同时设置文件访问权限,请参考以下示例代码。
// completeMultipartUploadRequest.setObjectACL(CannedAccessControlList.Private);
// 指定是否列举当前UploadId已上传的所有Part。仅在Java SDK为3.14.0及以上版本时,支持通过服务端List分片数据来合并完整文件时,将CompleteMultipartUploadRequest中的partETags设置为null。
// Map<String, String> headers = new HashMap<String, String>();
// 如果指定了x-oss-complete-all:yes,则OSS会列举当前UploadId已上传的所有Part,然后按照PartNumber的序号排序并执行CompleteMultipartUpload操作。
// 如果指定了x-oss-complete-all:yes,则不允许继续指定body,否则报错。
// headers.put("x-oss-complete-all","yes");
// completeMultipartUploadRequest.setHeaders(headers);
// 完成分片上传。
CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
System.out.println(completeMultipartUploadResult.getETag());
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
1.3断点续传:
在上传大文件(超过5 GB)到OSS的过程中,如果出现网络中断、程序异常退出等问题导致文件上传失败,甚至重试多次仍无法完成上传,需要使用断点续传上传的方式。断点续传上传将需要上传的大文件分成多个较小的分片并发上传,加速上传完成时间。如果上传过程中,某一分片上传失败,再次上传时会从Checkpoint文件记录的断点继续上传,无需重新上传所有分片。上传完成后,所有分片将合并成完整的文件。
public class Demo {
public static void main(String[] args) {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
ObjectMetadata meta = new ObjectMetadata();
// 指定上传的内容类型。
meta.setContentType("text/plain");
// 文件上传时设置访问权限ACL。
// meta.setObjectAcl(CannedAccessControlList.Private);
// 通过UploadFileRequest设置多个参数。
// 依次填写Bucket名称(例如examplebucket)以及Object完整路径(例如exampledir/exampleobject.txt),Object完整路径中不能包含Bucket名称。
UploadFileRequest uploadFileRequest = new UploadFileRequest("examplebucket","exampledir/exampleobject.txt");
// 通过UploadFileRequest设置单个参数。
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
uploadFileRequest.setUploadFile("D:\\localpath\\examplefile.txt");
// 指定上传并发线程数,默认值为1。
uploadFileRequest.setTaskNum(5);
// 指定上传的分片大小,单位为字节,取值范围为100 KB~5 GB。默认值为100 KB。
uploadFileRequest.setPartSize(1 * 1024 * 1024);
// 开启断点续传,默认关闭。
uploadFileRequest.setEnableCheckpoint(true);
// 记录本地分片上传结果的文件。上传过程中的进度信息会保存在该文件中,如果某一分片上传失败,再次上传时会根据文件中记录的点继续上传。上传完成后,该文件会被删除。
// 如果未设置该值,默认与待上传的本地文件同路径,名称为${uploadFile}.ucp。
uploadFileRequest.setCheckpointFile("yourCheckpointFile");
// 文件的元数据。
uploadFileRequest.setObjectMetadata(meta);
// 设置上传回调,参数为Callback类型。
//uploadFileRequest.setCallback("yourCallbackEvent");
// 断点续传上传。
ossClient.uploadFile(uploadFileRequest);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (Throwable ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
// 关闭OSSClient。
if (ossClient != null) {
ossClient.shutdown();
}
}
}}
1.4上传回调:
上传回调的一种典型应用场景是结合授权第三方上传时使用。适当使用上传回调机制,能有效降低客户端的逻辑复杂度和网络消耗。上传回调流程如下:
目前仅简单上传(PutObject)、表单上传(PostObject)、完成分片上传(CompleteMultipartUpload)操作支持使用上传回调。
public class Demo {
public static void main(String[] args) throws Exception{
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = "exampledir/exampleobject.txt";
// 您的回调服务器地址,例如https://example.com:23450。
String callbackUrl = "yourCallbackServerUrl";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
String content = "Hello OSS";
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName,new ByteArrayInputStream(content.getBytes()));
// 上传回调参数。
Callback callback = new Callback();
callback.setCallbackUrl(callbackUrl);
//(可选)设置回调请求消息头中Host的值,即您的服务器配置Host的值。
// callback.setCallbackHost("yourCallbackHost");
// 设置发起回调时请求body的值。
callback.setCallbackBody("{\\\"mimeType\\\":${mimeType},\\\"size\\\":${size}}");
// 设置发起回调请求的Content-Type。
callback.setCalbackBodyType(Callback.CalbackBodyType.JSON);
// 设置发起回调请求的自定义参数,由Key和Value组成,Key必须以x:开始。
callback.addCallbackVar("x:var1", "value1");
callback.addCallbackVar("x:var2", "value2");
putObjectRequest.setCallback(callback);
PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
// 读取上传回调返回的消息内容。
byte[] buffer = new byte[1024];
putObjectResult.getResponse().getContent().read(buffer);
// 数据读取完成后,获取的流必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。
putObjectResult.getResponse().getContent().close();
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (Throwable ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
1.5上传进度条
在上传大文件到OSS时,为了让用户知道上传进度和预估剩余时间,可以利用OSS SDK提供的进度监听功能实现一个进度条来反馈实时的上传状态。
// 使用进度条,需要实现ProgressListener方法
public class PutObjectProgressListenerDemo implements ProgressListener {
private long bytesWritten = 0;
private long totalBytes = -1;
private boolean succeed = false;
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,完整路径中不能包含Bucket名称。例如exampledir/exampleobject.txt。
String objectName = "exampledir/exampleobject.txt";
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
String pathName = "D:\\localpath\\examplefile.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
// 上传文件的同时指定进度条参数。此处PutObjectProgressListenerDemo为调用类的类名,请在实际使用时替换为相应的类名。
ossClient.putObject(new PutObjectRequest(bucketName,objectName, new File(pathName)).
<PutObjectRequest>withProgressListener(new PutObjectProgressListenerDemo()));
// 下载文件的同时指定进度条参数。此处GetObjectProgressListenerDemo为调用类的类名,请在实际使用时替换为相应的类名。
// ossClient.getObject(new GetObjectRequest(bucketName,objectName).
// <GetObjectRequest>withProgressListener(new GetObjectProgressListenerDemo()));
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
public boolean isSucceed() {
return succeed;
}
// 使用进度条需要您重写回调方法,以下仅为参考示例。
@Override
public void progressChanged(ProgressEvent progressEvent) {
long bytes = progressEvent.getBytes();
ProgressEventType eventType = progressEvent.getEventType();
switch (eventType) {
case TRANSFER_STARTED_EVENT:
System.out.println("Start to upload......");
break;
case REQUEST_CONTENT_LENGTH_EVENT:
this.totalBytes = bytes;
System.out.println(this.totalBytes + " bytes in total will be uploaded to OSS");
break;
case REQUEST_BYTE_TRANSFER_EVENT:
this.bytesWritten += bytes;
if (this.totalBytes != -1) {
int percent = (int)(this.bytesWritten * 100.0 / this.totalBytes);
System.out.println(bytes + " bytes have been written at this time, upload progress: " + percent + "%(" + this.bytesWritten + "/" + this.totalBytes + ")");
} else {
System.out.println(bytes + " bytes have been written at this time, upload ratio: unknown" + "(" + this.bytesWritten + "/...)");
}
break;
case TRANSFER_COMPLETED_EVENT:
this.succeed = true;
System.out.println("Succeed to upload, " + this.bytesWritten + " bytes have been transferred in total");
break;
case TRANSFER_FAILED_EVENT:
System.out.println("Failed to upload, " + this.bytesWritten + " bytes have been transferred");
break;
default:
break;
}
}
}
3、下载文件其他形式:
3.1、简单下载:
简单下载指的是使用OSS API的GetObject接口,下载已上传的文件(Object),适用于一次HTTP请求交互即可完成下载的场景。
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
//从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写不包含Bucket名称在内的Object完整路径,例如testfolder/exampleobject.txt。
String objectName = "testfolder/exampleobject.txt";
// 填写Object下载到本地的完整路径。
String pathName = "D:\\localpath\\examplefile.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
// 下载Object到本地文件,并保存到指定的本地路径中。如果指定的本地文件存在会覆盖,不存在则新建。
// 如果未指定本地路径,则下载后的文件默认保存到示例程序所属项目对应本地路径中。
ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(pathName));
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
3.2、断点续传下载
在下载OSS大文件(超过5 GB)到本地的过程中,如果出现网络中断、程序异常退出等问题导致文件下载失败,甚至重试多次仍无法完成下载,需要使用断点续传下载的方式。断点续传下载将需要下载的大文件分成多个较小的分片并发下载,加速下载完成时间。如果下载过程中,某一分片下载失败,再次下载时会从Checkpoint文件记录的断点继续下载,无需重新下载所有分片。下载完成后,所有分片将合并成完整的文件。
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = "exampledir/exampleobject.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
// 请求10个任务并发下载。
DownloadFileRequest downloadFileRequest = new DownloadFileRequest(bucketName, objectName);
// 指定Object下载到本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
downloadFileRequest.setDownloadFile("D:\\localpath\\examplefile.txt");
// 设置分片大小,单位为字节,取值范围为100 KB~5 GB。默认值为100 KB。
downloadFileRequest.setPartSize(1 * 1024 * 1024);
// 设置分片下载的并发数,默认值为1。
downloadFileRequest.setTaskNum(10);
// 开启断点续传下载,默认关闭。
downloadFileRequest.setEnableCheckpoint(true);
// 设置断点记录文件的完整路径,例如D:\\localpath\\examplefile.txt.dcp。
// 只有当Object下载中断产生了断点记录文件后,如果需要继续下载该Object,才需要设置对应的断点记录文件。下载完成后,该文件会被删除。
//downloadFileRequest.setCheckpointFile("D:\\localpath\\examplefile.txt.dcp");
// 下载文件。
DownloadFileResult downloadRes = ossClient.downloadFile(downloadFileRequest);
// 下载成功时,会返回文件元数据。
ObjectMetadata objectMetadata = downloadRes.getObjectMetadata();
System.out.println(objectMetadata.getETag());
System.out.println(objectMetadata.getLastModified());
System.out.println(objectMetadata.getUserMetadata().get("meta"));
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (Throwable ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}