阿里云oss实现文件上传

步骤:
1.https://oss.console.aliyun.com/overview
开通 对象存储OSS
2.查看文档:
常用入口=》API文档=》在帮助中心打开【https://help.aliyun.com/document_detail/31947.html?spm=5176.8465980.help.dexternal.4e701450Bu0s0M】
1)专业术语【https://help.aliyun.com/document_detail/31947.html】
Bucket:一个项目创建一个Bucket,存储空间
Object:对象是 OSS 存储数据的基本单元
Region:地域表示 OSS 的数据中心所在物理位置
Endpoint:访问OSS文件域名URL
AccessKey:访问密钥
读写权限:私有/公共度/公共读写
服务端加密:无
实施日志:不开通

3.上传方式【建议采用方式三】
方式一:
文件先上传到应用服务器,然后再上传到OSS
此方式会文件上传会经过后台服务器,占用大量带宽,导致用户访问其他业务卡顿。
方式二:
文件直接由前端通过js代码上传到oss中
此方式会暴露出oss文件的秘钥给浏览器,非常不安全。
方式三:
服务端签名后直传

image-20240420174833671

	1)用户向应用服务器请求上传Policy
	2)应用服务器返回上传Policy【由服务器控制上传地址等信息】
	3)用户直接上传OSS

4.获取子用户Accesskeys
1)鼠标移至账号头像,点击Accesskeys管理,使用子用户Accesskeys【首次使用需要开通RAM访问控制】
2)新增用户
登录名称:gulimall-wan
显示名称:gulimall
访问方式:编程访问

3)新增完成复制AccessKeyID和secret
4)添加权限:AliyunOSSFullAccess
5)修改CORS
	打开bucket -> 权限管理 -> 跨域设置 -> 设置 -> 创建规则
	来源:* 
	允许Headers:* 
	允许Methods:POST

使用原生sdk上传的demo:
https://help.aliyun.com/document_detail/91868.html?spm=a2c4g.11186623.2.16.1d2f7eaeOSyN4O#concept-ahk-rfz-2fb

使用aliyun封装的SDK实现上传,通过以下网址找到演示demo https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
***OSS放在单独第三方微服务模块
1.创建第三方微服务:
com.atguigu.gulimall
gulimall-third-party
谷粒商城-第三方服务
选择openFeign,SpringWeb
2.添加依赖
3.启动类注解添加,主pom添加模块
@EnableDiscoveryClient
<module>gulimall-third-party</module>

4.application.yml
server:
port: 30000

spring:
application:
name: gulimall-third-party
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
alicloud:
access-key: ************
secret-key: *************
oss:
endpoint: oss-cn-shanghai.aliyuncs.com
bucket: gulimall-wan

logging:
level:
com.atguigu.gulimall: debug

5.创建OssController,返回policy凭证【获取对象签名】
@RestController
public class OssController {

@Autowired
OSS ossClient;

@Value("${spring.cloud.alicloud.oss.endpoint}")
private String endpoint;
@Value("${spring.cloud.alicloud.oss.bucket}")
private String bucket;
@Value("${spring.cloud.alicloud.access-key}")
private String accessId;

@RequestMapping("/oss/policy")
public R policy() {
// https://gulimall-wan.oss-cn-shanghai.aliyuncs.com
String host = "https://" + bucket + "." + endpoint;

// callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
// String callbackUrl = "http://88.88.88.88:8888";

// 文件在bucket存储目录,若不存在则会自动创建路径。使用日期作为目录
String dir = new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + "/";

// 创建OSSClient实例。这里是alicloud starter自动配置,可自动注入
//OSS ossClient = new OSSClientBuilder().build(endpoint, accessId, accessKey);

Map<String, String> respMap = null;
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);

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));
// respMap.put("expire", formatISO8601Date(expiration));

// 下面是跨域设置,在网关统一解决跨域
// JSONObject jasonCallback = new JSONObject();
// jasonCallback.put("callbackUrl", callbackUrl);
// jasonCallback.put("callbackBody",
// "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
// jasonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");
// String base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());
// respMap.put("callback", base64CallbackBody);
//
// JSONObject ja1 = JSONObject.fromObject(respMap);
// // System.out.println(ja1.toString());
// response.setHeader("Access-Control-Allow-Origin", "*");
// response.setHeader("Access-Control-Allow-Methods", "GET, POST");
// response(request, response, ja1.toString());

} catch (Exception e) {
// Assert.fail(e.getMessage());
System.out.println(e.getMessage());
} finally {
ossClient.shutdown();
}
return R.ok().put("data", respMap);
}
}

6.配置网关
- id: third_party_route
uri: lb://gulimall-third-party
predicates:
- Path=/api/thirdparty/**
filters:
- RewritePath=/api/thirdparty/(?<segment>.*),/$\{segment}

前端配置

1
2
3
4
5
6
7
8
9
10
11
12
13
1.拷贝upload组件放到component中,修改multiUpload.vue和singleUpload.vue文件
修改成自己的外网Bucket域名
action="http://gulimall-wan.oss-cn-shanghai.aliyuncs.com"

2.然后在图片上传地址栏修改vue代码,使用单文件上传
在brand-add-or-update.vue中导入
1)import SingleUpload from "@/componets/upload/singleUpload"
2)在data 的components:{SingleUpload}
3)在</template>中就可以使用了 <single-upload>来代替之前的<el-input>标签【自定义节点】

3.设置跨域,允许bucket跨域请求
在oss里面修改管理控制台修改:
https://oss.console.aliyun.com/bucket/oss-cn-shanghai/gulimall-wan/permission/cors