之前的学习手记,有朋友需要,现在同步过来,请注意时效性!
什么是网页直传oss
传统的网页传输文件都会先把文件传输到后端服务器,再由后端服务器上传到oss空间
这样做的缺点是:
- 上传慢:用户数据需先上传到应用服务器,之后再上传到OSS。网络传输时间比直传到OSS多一倍。如果用户数据不通过应用服务器中转,而是直传到OSS,速度将大大提升。而且OSS采用BGP带宽,能保证各地各运营商之间的传输速度。
- 扩展性差:如果后续用户多了,应用服务器会成为瓶颈。
- 费用高:需要准备多台应用服务器。由于OSS上传流量是免费的,如果数据直传到OSS,不通过应用服务器,那么将能省下几台应用服务器。
我们可以直接在web端、小程序将文件直传oss空间,本期通过阿里云oss来作为案例展示
STS临时授权访问OSS
因为是网页端直传,所以网页中会保存我们的oss账户信息,这样是不安全的,推荐使用sts临时授权的方式来完成交互 文档地址
创建子用户
首先创建一个ram用户,勾选编程访问,创建好以后保存id和key
选中这个用户,点击添加权限,添加AliyunSTSAssumeRoleAccess这个权限,点击确定
创建权限策略
创建完用户以后,我们来创建一个策略,在策略中可以限定可以使用的权限和可以操作的文件夹
更多的策略配置可以查看RAM Policy概述
脚本
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"oss:PutObject"
],
"Resource": [
"acs:oss:*:*:loop"
]
}
]
}
创建角色
点击Ram角色管理,点击创建Ram角色,点击阿里云账号
点击完成以后,点击为角色授权,然后点击刚刚创建的权限策略
然后点击进入这个角色,保存ARN
获取token
创建一个springboot项目并添加依赖
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-sts</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.4.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
修改application.yml
,填入自己的配置文件
alioss:
endpoint: oss-cn-chengdu.aliyuncs.com
accessKeyId:
accessKeySecret:
roleArn:
regionID: cn-chengdu
bucket: loop
spring:
thymeleaf:
cache: false
创建配置类
@Component
@ConfigurationProperties(prefix = "alioss")
@Data
public class AliOssConfig {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String roleArn;
private String regionID;
private String bucket;
}
创建一个前端需要的对象OssTokenVO
@Data
@Builder
public class OssTokenVO {
private String accessKeyId;
private String accessKeySecret;
private String securityToken;
private String region;
private String bucket;
}
创建service AliOssService
@Service
public class AliOssService {
@Autowired
private AliOssConfig aliOssConfig;
/**
* 获取直传token
*
* @return
*/
public OssTokenVO getDirectToken() throws ClientException {
//构造请求器
IClientProfile profile = DefaultProfile.getProfile(aliOssConfig.getRegionID(),
aliOssConfig.getAccessKeyId(),
aliOssConfig.getAccessKeySecret());
DefaultAcsClient client = new DefaultAcsClient(profile);
AssumeRoleRequest request = new AssumeRoleRequest();
request.setRoleSessionName("loop");
request.setRoleArn(aliOssConfig.getRoleArn());
request.setDurationSeconds(1000L);
//发送请求
AssumeRoleResponse acsResponse = client.getAcsResponse(request);
AssumeRoleResponse.Credentials credentials = acsResponse.getCredentials();
//组装一个web需要的对象
String accessKeyId = credentials.getAccessKeyId();
String accessKeySecret = credentials.getAccessKeySecret();
String securityToken = credentials.getSecurityToken();
return OssTokenVO.builder()
.securityToken(securityToken)
.accessKeyId(accessKeyId)
.accessKeySecret(accessKeySecret)
.region("oss-" + aliOssConfig.getRegionID())
.bucket(aliOssConfig.getBucket())
.build();
}
}
简单写个控制器
@RestController
@RequestMapping("/oss")
public class OssController {
@Autowired
private AliOssService aliOssService;
@GetMapping("/token")
public OssTokenVO test() throws ClientException {
return aliOssService.getDirectToken();
}
}
测试一下
编写页面测试
编写一个测试页面index.html
,加个控制器跳转过去
public class IndexController {
@GetMapping
public ModelAndView index(ModelAndView modelAndView) {
modelAndView.setViewName("index");
return modelAndView;
}
}
引入依赖 aliyun-oss-sdk文档
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.13.2.min.js"></script>
写个选择文件
<input type="file" id="ossInput">
上传逻辑
document.getElementById("ossInput")
.addEventListener("input", (e) => {
//请求后端拿到token
axios.get('/oss/token')
.then(function (response) {
let ossConfig = response.data;
//实例化一个client
let client = new OSS({
region: ossConfig.region,
accessKeyId: ossConfig.accessKeyId,
accessKeySecret: ossConfig.accessKeySecret,
stsToken: ossConfig.securityToken,
bucket: ossConfig.bucket
});
//上传文件
client.put("test.png", e.target.files[0]);
})
})
设置oss存储空间的Headers
设置一下跨域
完成编写,此时点击选择文件上传便可以 直接上传到oss存储空间了