一、开通阿里云OSS功能并创建RAM账号
1、首先必须要了解的几个关于OSS的概念:
https://help.aliyun.com/document_detail/31947.html
中文 | 英文 | 说明 |
存储空间 | Bucket | 存储空间是您用于存储对象(Object)的容器,所有的对象都必须隶属于某个存储空间。 |
对象/文件 | Object | 对象是 OSS 存储数据的基本单元,也被称为OSS的文件。对象由元信息(Object Meta)、用户数据(Data)和文件名(Key)组成。对象由存储空间内部唯一的Key来标识。 |
地域 | Region | 地域表示 OSS 的数据中心所在物理位置。您可以根据费用、请求来源等综合选择数据存储的地域。详情请查看OSS已经开通的Region。 |
访问域名 | Endpoint | Endpoint 表示OSS对外服务的访问域名。OSS以HTTP RESTful API的形式对外提供服务,当访问不同地域的时候,需要不同的域名。通过内网和外网访问同一个地域所需要的域名也是不同的。具体的内容请参见各个Region对应的Endpoint。 |
访问秘钥 | AccessKey | AccessKey,简称 AK,指的是访问身份验证中用到的AccessKeyId 和AccessKeySecret。OSS通过使用AccessKeyId 和AccessKeySecret对称加密的方法来验证某个请求的发送者身份。AccessKeyId用于标识用户,AccessKeySecret是用户用于加密签名字符串和OSS用来验证签名字符串的密钥,其中AccessKeySecret 必须保密。 |
2、新增Bucket
创建成功:
Bucket管理界面如下:
3、开通RAM访问控制
https://help.aliyun.com/product/28625.html
创建完成后,必须要记得“添加权限”
之后,这个“AccessKey ID”和“SECRET”对就可以被正常使用了!
二、通过SDK上传文件——简单上传
https://help.aliyun.com/document_detail/32013.html
1、在maven中添加依赖:
<dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>3.8.0</version> </dependency>
2、测试代码如下:
@Test public void testUpload1() throws FileNotFoundException { // Endpoint以杭州为例,其它Region请按实际情况填写。 String endpoint = "oss-cn-shanghai.aliyuncs.com"; // 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维。 String accessKeyId = "LTAI4GG4TR1dMsFQU"; String accessKeySecret = "eJb8sWZUSk1ONpftVN"; // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 上传文件流。 InputStream inputStream = new FileInputStream("C:\\Users\\jigq\\Desktop\\子丹商城\\2\\2.jpg"); ossClient.putObject("zidanmall", "2.jpg", inputStream); // 关闭OSSClient。 ossClient.shutdown(); System.out.println("上传成功。。。"); }
3、测试结果:
简单上传成功!
三、SpringCloud Alibaba-OSS 服务上传
https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
1、引入springcloud alibaba oss的maven依赖
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alicloud-oss --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alicloud-oss</artifactId> <version>2.1.0.RELEASE</version> </dependency>
2、在application.yml中增加配置信息:
spring: cloud: alicloud: access-key: LTAI4GG4TR1dMsFQU226sb6h secret-key: eJb8sWZUSk1ONpftVNa287jns8KZGp oss: endpoint: oss-cn-shanghai.aliyuncs.com
3、测试代码将变得更加简单:
@Test public void testUpload2() throws FileNotFoundException { // 上传文件流。 InputStream inputStream = new FileInputStream("C:\\Users\\jigq\\Desktop\\子丹商城\\2\\3.jpg"); ossClient.putObject("zidanmall", "3.jpg", inputStream); // 关闭OSSClient。 ossClient.shutdown(); System.out.println("上传成功。。。"); }
测试成功!
四、最佳实践——服务端签名后直传
实际应用中,Web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠;
结合zidanmall,我们将所有的第三方服务,做成一个 zidanmall-third-party 模块:
1、pom.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.jiguiquan.zidanmall</groupId> <artifactId>zidanmall-third-party</artifactId> <version>0.0.1-SNAPSHOT</version> <name>zidanmall-third-party</name> <description>子丹商城-所有的第三方服务继承模块</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR3</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>com.jiguiquan.zidanmall</groupId> <artifactId>zidanmall-common</artifactId> <version>1.0-SNAPSHOT</version> <exclusions> <exclusion> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alicloud-oss</artifactId> <version>2.1.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2、bootstrap.yml:
server: port: 30000 spring: application: name: zidanmall-third-party cloud: nacos: discovery: server-addr: localhost:8848 config: server-addr: localhost:8848 file-extension: yaml namespace: f2e98e0e-63ec-44f5-8a9f-fdc797ab22bf group: dev refresh-enabled: true
3、application.yml:
spring: cloud: alicloud: access-key: LTAI4GG4TR1dMsFQU226sb6h secret-key: eJb8sWZUSk1ONpftVNa287jns8KZGp oss: endpoint: oss-cn-shanghai.aliyuncs.com bucket: zidanmall
4、返回签名的核心代码:
https://help.aliyun.com/document_detail/91868.html
@RestController public class OssController { @Autowired private OSS ossClient; @Value("${spring.cloud.alicloud.oss.bucket}") private String bucket; @Value("${spring.cloud.alicloud.oss.endpoint}") private String endpoint; @Value("${spring.cloud.alicloud.access-key}") private String accessId; /** * * @return */ @GetMapping("/oss/policy") public R policy(){ String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint // callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。 // String callbackUrl = "http://88.88.88.88:8888"; String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); String dir = format + "/"; // 用户上传文件时自定义的目录文件夹。 try { long expireTime = 30; long expireEndTime = System.currentTimeMillis() + expireTime * 1000; Date expiration = new Date(expireEndTime); // PostObject请求最大可支持的文件大小为5 GB,即CONTENT_LENGTH_RANGE为5*1024*1024*1024。 PolicyConditions policyConds = new PolicyConditions(); policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000); policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir); String postPolicy = ossClient.generatePostPolicy(expiration, policyConds); byte[] binaryData = postPolicy.getBytes("utf-8"); String encodedPolicy = BinaryUtil.toBase64String(binaryData); String postSignature = ossClient.calculatePostSignature(postPolicy); Map<String, String> respMap = new LinkedHashMap<String, String>(); respMap.put("accessid", accessId); respMap.put("policy", encodedPolicy); respMap.put("signature", postSignature); respMap.put("dir", dir); respMap.put("host", host); respMap.put("expire", String.valueOf(expireEndTime / 1000)); return new R().put("data", respMap); } catch (Exception e) { System.out.println(e.getMessage()); return null; } } }
5、最后,我们使用 Gateway做一下统一的路由转发:
spring: cloud: gateway: routes: - id: third_party_route uri: lb://zidanmall-third-party predicates: - Path=/api/thirdparty/** filters: - RewritePath=/api/thirdparty/(?<segment>/?.*), /$\{segment}
6、都完成后,我们通过网关访问一下此接口,看看是否能正常访问:
显然是OK的,这样我们的OSS服务端签名接口就完成了;
五、最后补充一点
当我们前端从后端获取到签名后,会直接调用阿里云的接口进行文件上传;
但是由于阿里云的接口并没有经过我们的Gateway统一进行跨域允许设置,所以会碰到跨域问题;
所以我们必须要开启阿里云OSS文件上传的跨域支持:创建跨域规则:
这样,我们整个的OSS最佳实践的文件上传功能就算是实现了后端部分,与前端部分的整合,可以参见:
商品服务-品牌管理-三、使用阿里云OSS服务实现logo文件的上传