开通配置阿里云oss
-
购买阿里云oss服务
-
创建一个Bucket
-
增加子账号并赋予权限
记录下面信息,后续需要使用
给新创建的账号添加权限
-
配置oss权限
-
设置oss跨域
后端代码编写
- 添加
aliyun-sdk-oss
等相关依赖<dependencies> <!--springboot-web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--阿里云oss--> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> </dependency> <!--hutool--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> </dependency> </dependencies>
- 配置文件
aliyun: oss: endpoint: oss-cn-shanghai.aliyuncs.com # oss对外服务的访问域名 accessKeyId: LTAI5tN2xxxxxxxxx # 访问身份验证中用到用户标识 accessKeySecret: FqRbVFpKxxxxxxxxxxxx # 用户用于加密签名字符串和oss用来验证签名字符串的密钥 bucketName: polars-dev # oss的存储空间 policy: expire: 300 # 签名有效期(S) maxSize: 10 # 上传文件大小(M) callback: http://liboshuai.com:28080/polaris-pms-service/aliyun/oss/callback # 文件上传成功后的回调地址 dir: prefix: polaris/images/ # 上传文件夹路径前缀
- oss配置类
package com.liboshuai.polaris.common.file.aliyun.config; import com.aliyun.oss.OSSClient; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @Author: liboshuai * @Date: 2023-02-13 17:29 * @Description: */ @Configuration public class AliyunOssConfig { @Value("${aliyun.oss.endpoint}") private String ALIYUN_OSS_ENDPOINT; @Value("${aliyun.oss.accessKeyId}") private String ALIYUN_OSS_ACCESSKEYID; @Value("${aliyun.oss.accessKeySecret}") private String ALIYUN_OSS_ACCESSKEYSECRET; @Bean public OSSClient ossClient(){ return new OSSClient(ALIYUN_OSS_ENDPOINT,ALIYUN_OSS_ACCESSKEYID,ALIYUN_OSS_ACCESSKEYSECRET); } }
- oss上传结果vo对象
package com.liboshuai.polaris.common.file.aliyun.vo; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @Author: liboshuai * @Date: 2023-02-13 17:30 * @Description: 阿里云文件上传结果 */ @Data public class AliyunOssPolicyResult { @ApiModelProperty("访问身份验证中用到用户标识") private String accessKeyId; @ApiModelProperty("用户表单上传的策略,经过base64编码过的字符串") private String policy; @ApiModelProperty("对policy签名后的字符串") private String signature; @ApiModelProperty("上传文件夹路径前缀") private String dir; @ApiModelProperty("oss对外服务的访问域名") private String host; @ApiModelProperty("上传成功后的回调设置") private String callback; }
- oss回调接口入参vo对象
package com.liboshuai.polaris.common.file.aliyun.vo; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @Author: liboshuai * @Date: 2023-02-13 17:33 * @Description: 阿里云文件上传回调入参 */ @Data public class AliyunOssCallbackParam { @ApiModelProperty("请求的回调地址") private String callbackUrl; @ApiModelProperty("回调是传入request中的参数") private String callbackBody; @ApiModelProperty("回调时传入参数的格式,比如表单提交形式") private String callbackBodyType; }
- oss回调接口结果vo对象
package com.liboshuai.polaris.common.file.aliyun.vo; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @Author: liboshuai * @Date: 2023-02-13 17:44 * @Description: */ @Data public class AliyunOssCallbackResult { @ApiModelProperty("文件名称") private String filename; @ApiModelProperty("文件大小") private String size; @ApiModelProperty("文件的mimeType") private String mimeType; @ApiModelProperty("图片文件的宽") private String width; @ApiModelProperty("图片文件的高") private String height; }
- oss文件上传service
package com.liboshuai.polaris.common.file.aliyun.service; import com.liboshuai.polaris.common.file.aliyun.vo.AliyunOssCallbackResult; import com.liboshuai.polaris.common.file.aliyun.vo.AliyunOssPolicyResult; import javax.servlet.http.HttpServletRequest; /** * @Author: liboshuai * @Date: 2023-02-13 18:27 * @Description: */ public interface OssService { /** * oss上传策略生成 */ AliyunOssPolicyResult policy(); /** * oss上传成功回调 */ AliyunOssCallbackResult callback(HttpServletRequest request); }
package com.liboshuai.polaris.common.file.aliyun.service.impl; import cn.hutool.json.JSONUtil; import com.aliyun.oss.OSSClient; import com.aliyun.oss.common.utils.BinaryUtil; import com.aliyun.oss.model.MatchMode; import com.aliyun.oss.model.PolicyConditions; import com.liboshuai.polaris.common.file.aliyun.service.OssService; import com.liboshuai.polaris.common.file.aliyun.vo.AliyunOssCallbackParam; import com.liboshuai.polaris.common.file.aliyun.vo.AliyunOssCallbackResult; import com.liboshuai.polaris.common.file.aliyun.vo.AliyunOssPolicyResult; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.text.SimpleDateFormat; import java.util.Date; /** * @Author: liboshuai * @Date: 2023-02-13 17:36 * @Description: */ @Slf4j @Service public class AliyunOssServiceImpl implements OssService { @Value("${aliyun.oss.policy.expire}") private int ALIYUN_OSS_EXPIRE; @Value("${aliyun.oss.maxSize}") private int ALIYUN_OSS_MAX_SIZE; @Value("${aliyun.oss.callback}") private String ALIYUN_OSS_CALLBACK; @Value("${aliyun.oss.bucketName}") private String ALIYUN_OSS_BUCKET_NAME; @Value("${aliyun.oss.endpoint}") private String ALIYUN_OSS_ENDPOINT; @Value("${aliyun.oss.dir.prefix}") private String ALIYUN_OSS_DIR_PREFIX; @Autowired private OSSClient ossClient; /** * 签名生成 */ @Override public AliyunOssPolicyResult policy() { AliyunOssPolicyResult result = new AliyunOssPolicyResult(); // 存储目录 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); String dir = ALIYUN_OSS_DIR_PREFIX+sdf.format(new Date()); // 签名有效期 long expireEndTime = System.currentTimeMillis() + ALIYUN_OSS_EXPIRE * 1000; Date expiration = new Date(expireEndTime); // 文件大小 long maxSize = ALIYUN_OSS_MAX_SIZE * 1024 * 1024; // 回调 AliyunOssCallbackParam callback = new AliyunOssCallbackParam(); callback.setCallbackUrl(ALIYUN_OSS_CALLBACK); callback.setCallbackBody("filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}"); callback.setCallbackBodyType("application/x-www-form-urlencoded"); // 提交节点 String action = "http://" + ALIYUN_OSS_BUCKET_NAME + "." + ALIYUN_OSS_ENDPOINT; try { PolicyConditions policyConds = new PolicyConditions(); policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize); policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir); String postPolicy = ossClient.generatePostPolicy(expiration, policyConds); byte[] binaryData = postPolicy.getBytes("utf-8"); String policy = BinaryUtil.toBase64String(binaryData); String signature = ossClient.calculatePostSignature(postPolicy); String callbackData = BinaryUtil.toBase64String(JSONUtil.parse(callback).toString().getBytes("utf-8")); // 返回结果 result.setAccessKeyId(ossClient.getCredentialsProvider().getCredentials().getAccessKeyId()); result.setPolicy(policy); result.setSignature(signature); result.setDir(dir); result.setCallback(callbackData); result.setHost(action); } catch (Exception e) { log.error("签名生成失败", e); } return result; } @Override public AliyunOssCallbackResult callback(HttpServletRequest request) { AliyunOssCallbackResult result= new AliyunOssCallbackResult(); String filename = request.getParameter("filename"); filename = "https://".concat(ALIYUN_OSS_BUCKET_NAME).concat(".").concat(ALIYUN_OSS_ENDPOINT).concat("/").concat(filename); log.info("----ossCallBack-fileName: {}-------", filename); result.setFilename(filename); result.setSize(request.getParameter("size")); result.setMimeType(request.getParameter("mimeType")); result.setWidth(request.getParameter("width")); result.setHeight(request.getParameter("height")); return result; } }
- oss文件上传controller接口
package com.liboshuai.polaris.pms.service.controller; import com.liboshuai.polaris.common.domain.ResponseResult; import com.liboshuai.polaris.common.file.aliyun.service.OssService; import com.liboshuai.polaris.common.file.aliyun.vo.AliyunOssCallbackResult; import com.liboshuai.polaris.common.file.aliyun.vo.AliyunOssPolicyResult; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; /** * @Author: liboshuai * @Date: 2023-02-13 18:03 * @Description: */ @Slf4j @Controller @Api(tags = "OssController", description = "Oss管理") @NoArgsConstructor @RequestMapping("/aliyun/oss") public class OssController { private OssService ossService; @Autowired public OssController(OssService ossService) { this.ossService = ossService; } @ApiOperation(value = "oss上传签名生成") @RequestMapping(value = "/policy", method = RequestMethod.GET) @ResponseBody public ResponseResult<AliyunOssPolicyResult> policy() { AliyunOssPolicyResult result = ossService.policy(); return ResponseResult.success(result); } @ApiOperation(value = "oss上传成功回调") @RequestMapping(value = "/callback", method = RequestMethod.POST) @ResponseBody public ResponseResult<AliyunOssCallbackResult> callback(HttpServletRequest request) { log.info("--------进入oss回调接口--------"); AliyunOssCallbackResult ossCallbackResult = ossService.callback(request); return ResponseResult.success(ossCallbackResult); } }
前端代码
<template>
<div>
<el-upload
:action="useOss?ossUploadUrl:minioUploadUrl"
:data="useOss?dataObj:null"
list-type="picture"
:multiple="false" :show-file-list="showFileList"
:file-list="fileList"
:before-upload="beforeUpload"
:on-remove="handleRemove"
:on-success="handleUploadSuccess"
:on-preview="handlePreview">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过10MB</div>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="fileList[0].url" alt="">
</el-dialog>
</div>
</template>
<script>
import {policy} from '@/api/oss'
export default {
name: 'singleUpload',
props: {
value: String
},
computed: {
imageUrl() {
return this.value;
},
imageName() {
if (this.value != null && this.value !== '') {
return this.value.substr(this.value.lastIndexOf("/") + 1);
} else {
return null;
}
},
fileList() {
return [{
name: this.imageName,
url: this.imageUrl
}]
},
showFileList: {
get: function () {
return this.value !== null && this.value !== ''&& this.value!==undefined;
},
set: function (newValue) {
}
}
},
data() {
return {
dataObj: {
policy: '',
signature: '',
key: '',
ossaccessKeyId: '',
dir: '',
callback:'',
host: ''
},
dialogVisible: false,
useOss:true, //使用oss->true;使用MinIO->false
ossUploadUrl:'https://polars-dev.oss-cn-shanghai.aliyuncs.com',
minioUploadUrl:'http://localhost:8080/minio/upload',
};
},
methods: {
emitInput(val) {
this.$emit('input', val)
},
handleRemove(file, fileList) {
this.emitInput('');
},
handlePreview(file) {
this.dialogVisible = true;
},
beforeUpload(file) {
let _self = this;
if(!this.useOss){
//不使用oss不需要获取策略
return true;
}
return new Promise((resolve, reject) => {
policy().then(response => {
_self.dataObj.policy = response.data.policy;
_self.dataObj.signature = response.data.signature;
_self.dataObj.ossaccessKeyId = response.data.accessKeyId;
_self.dataObj.key = response.data.dir + '/${filename}';
_self.dataObj.dir = response.data.dir;
_self.dataObj.host = response.data.host;
_self.dataObj.callback = response.data.callback;
resolve(true)
}).catch(err => {
console.log(err)
reject(false)
})
})
},
handleUploadSuccess(res, file) {
this.showFileList = true;
this.fileList.pop();
let url = this.dataObj.host + '/' + this.dataObj.dir + '/' + file.name;
if(!this.useOss){
//不使用oss直接获取图片路径
url = res.data.url;
}
this.fileList.push({name: file.name, url: url});
this.emitInput(this.fileList[0].url);
}
}
}
</script>
<style>
</style>
功能演示
登录oss控制台,可以查看到我们刚刚上传的图片