后端进行sts认证生成临时身份凭证,前端通过凭证直传图片等文件到OSS中
一 OSS配置
增加用户和角色,创建OSS bucket
1.1 添加用户
登录阿里云管理控制台,右侧头像,进入访问控制
点击左侧导航栏的身份管理的用户,点击添加用户
输入名称,点击open api调用访问,确定
点击刚创建的用户,点击权限管理,点击新增授权
搜索sts,添加
在认证管理中
创建一个accesskey,并记录保存,后续需要使用
1.2 添加角色
在左侧导航栏中身份管理点击角色,创建角色
选择阿里云账号
填入有意义的名称,选择当前云账号信任
点击新创建的角色,添加授权,搜索oss,将两个权限都添加
同时,在角色信息中,将arn记录保存,后续需要使用
1.3 bucket创建
在对象存储中,创建bucket
如果需要公共读,则勾选公共读,如果仅自己读写,则选择私有,这里我选择了公共读,地域我选择了深圳,根据服务器部署位置来选
创建完成后,进入bucket,在数据安全,选择跨域设置,点击创建规则
来源为请求服务器地址,这里演示我填*
点击概览,根据自己的选择,记下访问的endpoint,这里为选择了外网访问的endpoint
二 后端配置
springboot作为后端服务
2.1 添加maven依赖
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</version>
</dependency>
2.2 配置访问密钥
在yaml配置文件中添加
oss:
endpoint: sts.cn-shenzhen.aliyuncs.com
accessKeyId: ram sk id
accessKeySecret: ram sk s
bucket: bucket名
ram: ram
oss-endpoint: oss-xxx
其中
- endpoint添加sts的endpoint,如果添加oss的endpoint会报错
- accessKeyId 和 secret 是创建用户的accessKeyId和secret
- ram为 创建的角色的arn
- bucket是oss里的桶名称
- oss-endpoint是oss的bucket的endpoint
2.3 添加控制器接受请求创建sts token
package com.fooleryang.remark.controller;
/**
* title:OssController
* description: TODO
* date: 2023/11/9
* author: fooleryang
* version: 1.0
*/
@RestController
@RequestMapping("/api/oss")
@Slf4j
public class OssController {
@Value("${oss.accessKeyId}")
private String secretId;
@Value("${oss.accessKeySecret}")
private String secretKey;
@Value("${oss.bucket}")
private String bucketName;
@Value("${oss.endpoint}")
private String endpoint;
@Value("${oss.ram}")
private String ram;
@Value("${oss.ossendpoint}")
private String ossEndpoint;
@GetMapping("/aly")
public Map<String,String > getsts(String userEmail){
try {
// 添加endpoint。适用于Java SDK 3.12.0及以上版本。
DefaultProfile.addEndpoint("", "Sts", endpoint);
// 构造default profile。
IClientProfile profile = DefaultProfile.getProfile("", secretId, secretKey);
// 构造client。
DefaultAcsClient client = new DefaultAcsClient(profile);
final AssumeRoleRequest request = new AssumeRoleRequest();
// 适用于Java SDK 3.12.0及以上版本。
request.setSysMethod(MethodType.POST);
request.setRoleArn(ram);
//角色会话名称
request.setRoleSessionName(userEmail); //这里我通过前端传参获取,到时候可以查看文件是谁传的
// if(!aliOss.getPolicy().isEmpty()) request.setPolicy(aliOss.getPolicy());
request.setDurationSeconds(3600L);
final AssumeRoleResponse response = client.getAcsResponse(request);
AssumeRoleResponse.Credentials credentials = response.getCredentials();
Map<String, String> result = new HashMap<String, String>();
result.put("accessKeyId",credentials.getAccessKeyId());
result.put("accessKeySecret",credentials.getAccessKeySecret());
result.put("expiration",credentials.getExpiration());
result.put("securityToken",credentials.getSecurityToken());
result.put("region","oss-cn-shenzhen");
result.put("bucket",bucketName);
result.put("oss-endpoint",ossEndpoint);
return result;
}catch (Exception e) {
log.error("error:"+e.getMessage());
throw new RuntimeException(e);
}
}
}
三 vue前端
先请求后端得到token,在直传到oss
3.1 导入依赖
pnpm install ali-oss
3.2 上传功能
新建一个ts文件,用于请求后端接口得到token
这里我对axios进行了封装,请求按自己封装或者直接用axios都可
//获取临时凭证
export const getCOSSecretKey = (params) => {
return http.get(`/oss/aly`,params)
}
再建一个ts文件,用于上传文件到oss
import OSS from 'ali-oss'
export const uploadObject = async (file, callback) => {
let fileName = file.name || ""
const origin_file_name = fileName.split(".").slice(0, fileName.split(".").length - 1).join('.') // 获取文件名称
// 获取当前时间戳
const upload_file_name = new Date().getTime() + '.' + fileName.split(".")[fileName.split(".").length - 1] // 文件上传名称定义为当前时间戳
//请求接口得到token
let res = await getCOSSecretKey( {
"emial":"xxx"
});
if(!res.data) return console.error('credentials invalid')
//启动OSS客户端
let stsConfig = res.data
const client = new OSS({
region: stsConfig.region,
// 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
accessKeyId: stsConfig.accessKeyId,
accessKeySecret: stsConfig.accessKeySecret,
// 从STS服务获取的安全令牌(SecurityToken)。
stsToken: stsConfig.securityToken,
// 填写Bucket名称,例如examplebucket。
bucket: stsConfig.bucket,
});
if(file.size>= 10 * 1024 * 1024){ //分片上传
result = await client.multipartUpload(upload_file_name, file, {
// 获取分片上传进度、断点和返回值。
progress: (p, cpt, res) => {
// onUploadProgress&&onUploadProgress(p)
},
// 设置并发上传的分片数量。
parallel: 4,
// 设置分片大小。默认值为1 MB,最小值为100 KB。
partSize: 1024 * 1024,
// headers,
// 自定义元数据,通过HeadObject接口可以获取Object的元数据。
mime: "text/plain",
timeout: 120000 // 设置超时时间
});
callback(result.url)
}else{
result = await client.put(upload_file_name, file)
callback(result.url)
}
}
四 vditor 图片上传调用
在使用vditor时,可以将图片上传到oss然后将返回的url插入到vditor中
具体过程如下:
4.1 vditor配置
创建vditor对象时加入upload配置
callback会将返回的url进行插入到内容中
vditor.value = new Vditor('vditor',{
upload: {
accept: "image/*",
multiple: false,
filename(name) {
return name
.replace(/[^(a-zA-Z0-9\u4e00-\u9fa5\.)]/g, "")
.replace(/[\?\\/:|<>\*\[\]\(\)\$%\{\}@~]/g, "")
.replace("/\\s/g", "");
},
handler(files) {
function callback(path) {
let name = files[0] && files[0].name;
let succFileText = "";
// if (vditor && vditor.value.currentMode === "wysiwyg") {
succFileText += `\n <img alt=${name} src="${path}">`;
// } else {
// succFileText += ` \n![${name}](${path})`;
// }
document.execCommand("insertHTML", false, succFileText);
}
handleImageUpload(files, callback);
},
url(files, callback) {
handleImageUpload(files, callback);
}
}
}
)
4.2 自定义图片上传
这里就调用了步骤三中的上传功能,上传到OSS中
const handleImageUpload = async (file,callback) => {
let res = await uploadObject(file,(url)=>{
callback(url)
})
}