一、OSS(对象存储服务)
1、介绍
对象存储服务:阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
OSS官方介绍地址:https://help.aliyun.com/document_detail/31947.html
使用前提:必须开通OSS服务
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201230162456675.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyMjAwMTYz,size_16,color_FFFFFF,t_70#pic_center)
二、使用OSS上传图片
1、引入Maven依赖
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
2、配置yml
server:
port: 9999
spring:
application:
name: marketing-third
oss:
accessId: LTAI4G2PSmNiCPnqaTdc5JUS
accessKey: OVmknks3UYf3nKz4dougCrRK6K76NX
bucketName: marketing-shop
endPointKey: oss-cn-beijing.aliyuncs.com
url: https://marketing-shop.oss-cn-beijing.aliyuncs.com
3、启动类
@SpringBootApplication
public class MarketingThirdApplication {
public static void main(String[] args) {
SpringApplication.run(MarketingThirdApplication.class, args);
}
}
4、config配置类
package com.itan.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "oss")
@Component
@Data
public class OssConfig {
private String accessId;
private String accessKey;
private String bucketName;
private String endPointKey;
private String url;
}
5、文件上传工具类
1、流式文件上传
2、web直传获取签名后上传
package com.itan.config;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.PolicyConditions;
import java.io.InputStream;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
public class AliOss {
private OSS ossClient;
private String bucketName;
public AliOss(String accessId, String accessKey, String bucketName, String endPoint) {
this.bucketName = bucketName;
this.ossClient = new OSSClientBuilder().build(endPoint, accessId, accessKey);
this.ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicReadWrite);
}
public void uploadFileInputStream(String fileName, InputStream inputStream) {
try {
this.ossClient.putObject(this.bucketName, fileName, inputStream);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
this.ossClient.shutdown();
}
}
public Map<String,String> getEncodedPolicyAndSignature(Date expiration, PolicyConditions policyConds) {
Map<String,String> map = new LinkedHashMap<String, String>();
try {
String policy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] bytes = policy.getBytes("utf-8");
String encodedPolicy = BinaryUtil.toBase64String(bytes);
String postSignature = ossClient.calculatePostSignature(policy);
map.put("encodedPolicy",encodedPolicy);
map.put("postSignature",postSignature);
} catch (Exception e) {
e.printStackTrace();
} finally {
ossClient.shutdown();
}
return map;
}
}
6、业务接口类
package com.itan.service;
import org.springframework.web.multipart.MultipartFile;
import java.util.Map;
public interface AliOssService {
String uploadFile(MultipartFile file);
Map<String, String> policy();
}
package com.itan.service.impl;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.itan.config.AliOss;
import com.itan.config.OssConfig;
import com.itan.service.AliOssService;
import com.itan.utils.BusinessException;
import com.itan.utils.ResultCodeAndMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
@Slf4j
@Service
public class AliOssServiceImpl implements AliOssService {
@Autowired
private OssConfig ossConfig;
@Override
public String uploadFile(MultipartFile file) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
if (null == file || file.isEmpty()) {
throw new BusinessException(ResultCodeAndMessage.build(ResultCodeAndMessage.BUSINESS_ERROR, "上传文件不能为空"));
}
String originalFilename = file.getOriginalFilename();
String fileName = System.currentTimeMillis() + originalFilename.substring(originalFilename.lastIndexOf("."));
String objName = sdf.format(new Date()) + "/" + fileName;
try {
AliOss aliOss = new AliOss(ossConfig.getAccessId(), ossConfig.getAccessKey(), ossConfig.getBucketName(), ossConfig.getEndPointKey());
aliOss.uploadFileInputStream(objName, file.getInputStream());
} catch (IOException e) {
throw new BusinessException(ResultCodeAndMessage.build(ResultCodeAndMessage.BUSINESS_ERROR, "上传文件阿里云服务异常"));
}
return ossConfig.getUrl() + objName;
}
@Override
public Map<String, String> policy() {
String dir = new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + "/";
AliOss aliOss = new AliOss(ossConfig.getAccessId(), ossConfig.getAccessKey(), ossConfig.getBucketName(), ossConfig.getEndPointKey());
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);
Map<String, String> map = aliOss.getEncodedPolicyAndSignature(expiration, policyConds);
map.put("accessId",ossConfig.getAccessId());
map.put("dir", dir);
map.put("host", ossConfig.getUrl());
map.put("expire", String.valueOf(expireEndTime / 1000));
return map;
}
}
7、controller类
package com.itan.controller;
import com.alibaba.fastjson.JSON;
import com.itan.service.AliOssService;
import com.itan.utils.BusinessException;
import com.itan.utils.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@Slf4j
@RestController
@RequestMapping("oss")
public class AliOssController {
@Autowired
private AliOssService aliOssService;
@PostMapping("upload")
public CommonResult upload(MultipartFile imageFile){
CommonResult result;
try {
result = CommonResult.successResult(aliOssService.uploadFile(imageFile));
} catch (BusinessException te) {
log.error(te.getErrorMessage(), te);
result = CommonResult.createResult(te.getResultCodeAndMessage());
}
log.info("上传文件到oss - 出参:{}", JSON.toJSONString(result));
return result;
}
@RequestMapping("policy")
public CommonResult policy(){
CommonResult result;
try {
result = CommonResult.successResult(aliOssService.policy());
} catch (BusinessException te) {
log.error(te.getErrorMessage(), te);
result = CommonResult.createResult(te.getResultCodeAndMessage());
}
log.info("web直传获取签名 - 出参:{}", JSON.toJSONString(result));
return result;
}
}
8、阿里云OSS配置跨域
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201230162437329.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyMjAwMTYz,size_16,color_FFFFFF,t_70#pic_center)
9、启动测试
接口地址:http://localhost:9999/oss/policy
返回参数:
{
"msg": {
"code": "20000",
"message": "请求成功"
},
"data": {
"encodedPolicy": "eyJleHBpcmF0aW9uIjoiMjAyMC0xMi0zMFQwODowMjowNC5zOTFaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjAwMF0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCIyMDIwLTEyLTMwLyJdXX0=",
"postSignature": "dEhfbmObhsp85c7xIXu0kY6oOC0=",
"accessId": "LTAI4G2PSmNiCPnqaTdc5JUS",
"dir": "2020-12-30/",
"host": "https://marketing-shop.oss-cn-beijing.aliyuncs.com/",
"expire": "1609315324"
},
"success": true
}
10、前端上传代码
获取签名
import http from '@/utils/httpRequest.js'
export function policy() {
return new Promise((resolve,reject)=>{
http({
url: http.adornUrl("/thirdparty/oss/policy"),
method: "get",
params: http.adornParams({})
}).then(({ data }) => {
resolve(data);
})
});
}
上传组件
<template>
<div>
<el-upload
action="http://marketing-shop.oss-cn-beijing.aliyuncs.com"
:data="dataObj"
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 './policy'
import { getUUID } from '@/utils'
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: '',
host: '',
},
dialogVisible: false
};
},
methods: {
emitInput(val) {
this.$emit('input', val)
},
handleRemove(file, fileList) {
this.emitInput('');
},
handlePreview(file) {
this.dialogVisible = true;
},
beforeUpload(file) {
let _self = this;
return new Promise((resolve, reject) => {
policy().then(response => {
_self.dataObj.policy = response.data.encodedPolicy;
_self.dataObj.signature = response.data.postSignature;
_self.dataObj.ossaccessKeyId = response.data.accessId;
_self.dataObj.key = response.data.dir + getUUID() + '_${filename}';
_self.dataObj.dir = response.data.dir;
_self.dataObj.host = response.data.host;
console.log("赋值后数据:",this.dataObj);
resolve(true)
}).catch(err => {
reject(false)
})
})
},
handleUploadSuccess(res, file) {
console.log("上传成功...")
this.showFileList = true;
this.fileList.pop();
this.fileList.push({name: file.name, url: this.dataObj.host + '/' + this.dataObj.key.replace("${filename}",file.name) });
this.emitInput(this.fileList[0].url);
}
}
}
</script>
<style>
</style>