文章目录
- 一,创建第三方服务模块thrid-party
- 1,创建一个名为`gulimall-third-party`的模块
- 2,nacos上创建third-party命名空间,用来管理这个服务的所有配置
- 3,配置pom文件
- 4,配置文件
- 5,单元测试
- 6,增加网关路由配置
- 二,后台提供生成密钥的接口
- 代码解释
- 使用说明
- 问题记录
一,创建第三方服务模块thrid-party
根据图片的架构设计,前端上传文件的步骤如下:
- ①从后台获取签名
- ②携带签名将文件上传至阿里云OSS
因此,上传文件涉及到第三方服务阿里云OSS,以后还会有第三方短信服务等,为了统一管理第三方服务,创建一个专门的模块third-party。
1,创建一个名为gulimall-third-party
的模块
2,nacos上创建third-party命名空间,用来管理这个服务的所有配置
3,配置pom文件
OSS相关的包依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>aliyun-oss-spring-boot-starter</artifactId>
</dependency>
4,配置文件
application.properties。
server.port=30000
alibaba.cloud.secret-key=fzQdkkAR4D1dRopvBC40d1202jgb
alibaba.cloud.access-key=LTAI5tC6QtV3C5dzq7uau
alibaba.cloud.oss.endpoint=oss-cn-hangzhou.aliyuncs.com
spring.application.name=gulimall-third-party
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
bootstrap.yml。
spring:
application:
name: gulimall-third-party
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
namespace: 0ae75f1a-5bd3-4113-aec9-aad4a23403d7
5,单元测试
编写单元测试。
package com.atguigu.gulimall.thirdparty;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.aliyuncs.exceptions.ClientException;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.File;
@SpringBootTest
@RunWith(SpringRunner.class)
class GulimallThirdPartyApplicationTests {
@Autowired
private OSS ossClient;
@Test
void contextLoads() {
}
@Test
public void testUpload() throws ClientException {
String bucketName = "gulimallfuck";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "134.png";
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
String filePath= "C:\\Users\\Lenovo\\Desktop\\1.png";
// 创建OSSClient实例。
try {
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(filePath));
// 上传文件。
PutObjectResult result = ossClient.putObject(putObjectRequest);
} catch (Exception oe) {
oe.printStackTrace();
}
}
}
6,增加网关路由配置
- id: gulimall-third-party
uri: lb://gulimall-third-party
predicates:
- Path=/api/thirdparty/**
filters:
- RewritePath=/api/thirdparty/(?<segment>.*),/$\{segment}
二,后台提供生成密钥的接口
参考阿里云OSS文档,后端生成密钥的代码如下。
package com.atguigu.gulimall.thirdparty.controller;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.atguigu.common.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @Description:
* @Created: with IntelliJ IDEA.
* @createTime: 2020-05-27 15:56
**/
/**
*
*/
@RestController
public class OssController {
@Value("${alibaba.cloud.access-key}")
private String accessKeyId;
@Value("${alibaba.cloud.oss.endpoint}")
private String endpoint;
@Autowired
private OSS ossClient;
@RequestMapping("/oss/policy")
public R policy() {
String bucket = "gulimallfuck"; // 请填写您的 bucketname 。
String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
// callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
String dir = format + "/"; // 用户上传文件时指定的前缀。
// 创建OSSClient实例。
Map<String, String> respMap = null;
try {
long expireTime = 30;
long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
Date expiration = new Date(expireEndTime);
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);
respMap = new LinkedHashMap<String, String>();
respMap.put("accessid", accessKeyId);
respMap.put("policy", encodedPolicy);
respMap.put("signature", postSignature);
respMap.put("dir", dir);
respMap.put("host", host);
respMap.put("expire", String.valueOf(expireEndTime / 1000));
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
ossClient.shutdown();
}
return R.ok().put("data",respMap);
}
}
这段代码展示了如何生成一个预签名的策略(policy),允许客户端通过POST方式上传文件到阿里云OSS服务。policy
方法返回了一个LinkedHashMap
类型的respMap
,该映射包含了客户端上传文件所需的参数。下面是respMap
中各个键值对的作用解释:
-
accessid:
- 作用: 客户端上传文件时的身份标识,即Access Key ID。
- 用途: 验证客户端的身份。
-
policy:
- 作用: 一个Base64编码的JSON字符串,定义了上传文件的策略条件。
- 用途: 客户端上传文件时需要携带此策略,以满足预设的限制条件。
-
signature:
- 作用: 对
policy
进行签名的结果,确保策略的完整性和安全性。 - 用途: 客户端上传文件时需要携带此签名,以证明策略的有效性。
- 作用: 对
-
dir:
- 作用: 文件上传的目标目录前缀。
- 用途: 指定文件上传后的存储位置前缀,便于组织和管理文件。
-
host:
- 作用: OSS服务的访问域名。
- 用途: 客户端通过此域名发起上传请求。
-
expire:
- 作用: 策略的有效截止时间(以秒为单位的时间戳)。
- 用途: 客户端必须在此时间戳之前完成文件上传。
代码解释
假设我们想要允许客户端上传文件到名为gulimallfuck
的Bucket中,并且文件会被存储在2023-07-25/
目录下。policy
方法会生成一个策略,该策略包含以下限制:
- 文件大小范围在0到1048576000字节之间。
- 文件名必须以
2023-07-25/
开头。
客户端在发起POST请求时需要携带这些参数,以符合策略的要求。如果所有条件都满足,文件将被成功上传到OSS。
使用说明
-
客户端生成表单:
- 客户端(通常是前端JavaScript代码)会根据返回的
respMap
构建一个HTML表单,包含所有的必要字段。
- 客户端(通常是前端JavaScript代码)会根据返回的
-
表单提交:
- 当用户选择文件后,表单会通过POST方式提交到OSS服务,文件作为表单的一部分被上传。
-
OSS验证:
- OSS服务会验证
accessid
、policy
和signature
,确保它们有效且符合策略条件。
- OSS服务会验证
-
文件存储:
- 如果验证通过,文件将被存储在指定的Bucket和目录中。
问题记录
参考文章:https://blog.csdn.net/epitomizelu/article/details/140608401