一、注冊阿里云賬號并開通OSS服務
1、登錄阿里云賬號
2、創(chuàng)建一個bucket
3、創(chuàng)建子用戶
對自用戶分配權限,打開操作OSS的全部權限(也可根據(jù)業(yè)務需求進行更改)
4、配置上傳跨域規(guī)則
- 任何來源: *
- 允許方法: POST
- 任何請求頭Headers: *
二、文件上傳方式
1、服務器直傳方式
每個OSS的用戶都會用到上傳服務。Web端常見的上傳方法是用戶在瀏覽器或App端上傳文件到應用服務器,應用服務器再把文件上傳到OSS
和數(shù)據(jù)直傳到OSS相比,以上方法有三個缺點:
- 上傳慢:用戶數(shù)據(jù)需先上傳到到應用服務器,之后再上傳到OSS。網(wǎng)絡傳輸時間比直傳到OSS多一倍。如果用于數(shù)據(jù)不通過應用服務器中轉,而是直傳到OSS,速度將大大提升。而且OSS采用BGP帶寬,能保證各地各運營商之間的傳輸速度
- 擴展性差:如果后續(xù)用戶多了,應用服務器會成為瓶頸
- 費用高:需要準備多臺應用服務器。由于OSS上傳流量是免費的,如果數(shù)據(jù)直傳到OSS,不通過應用服務器,那么將能省下幾臺應用服務器
2、服務端簽名后前端直傳
Web前端服務端請求簽名,然后前端(Vue)直接上傳,不會對服務端產生壓力,而且安全可靠。
相關資料:服務端簽名直傳并設置上傳回調概述
Java連接實例:Java實踐OSS
上傳回調流程
- Web前端請求應用服務器,獲取上傳所需參數(shù)(如OSS的accessKeyId、policy、callback等參數(shù))
- 應用服務器返回相關參數(shù)
- Web前端直接向OSS服務發(fā)起上傳文件請求
- 等上傳完成后OSS服務會回調應用服務器的回調接口
- 應用服務器返回響應給OSS服務
- OSS服務將應用服務器回調接口的內容返回給Web前端
3、SpringBoot整合OSS實現(xiàn)文件上傳
1、在pom.xml中添加相關依賴
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
2、修改SpringBoot配置文件
#操作oss需要的一些參數(shù)
aliyun:
oss:
accessKeyId: xxx # 阿里云的accessKeyId
accessKeySecret: xxx # accessKey 密碼
endPoint: xxx # Endpoint:在阿里云oss控制臺查看自己使用的endpoint,eg: oss-cn-shanghai.aliyuncs.com
bucketName: xxx # bucket 名稱
policy:
expire: 300 # 簽名有效期(S)
maxSize: 10 # 上傳文件大小(M)
callback: http://localhost:8080/aliyun/oss/callback # 文件上傳成功后的回調地址
dir:
prefix: xxx/images/ # 上傳文件夾路徑前綴
3、添加OSS的相關Java配置
用于配置OSS的連接客戶端的OSSClient
/**
* TODO 用于配置OSS的連接客戶端OSSClient
*
* @author ss_419
* @version 1.0
* @date 2023/5/28 19:04
*/
@Configuration
@Component
public class OssConfig {
@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);
}
}
4、封裝前端上傳策略返回對象
前端直傳時所需要的參數(shù)
package org.pp.oss.model;
/**
* TODO 獲取OSS上傳文件授權返回結果
*
* @author ss_419
* @version 1.0
* @date 2023/5/28 19:07
*/
public class OssPolicyResult {
private String accessKeyId;
// @ApiModelProperty("用戶表單上傳的策略,經過base64編碼過的字符串") 13
private String policy;
// @ApiModelProperty("對policy簽名后的字符串") 15
private String signature;
// @ApiModelProperty("上傳文件夾路徑前綴") 17
private String dir;
// @ApiModelProperty("oss對外服務的訪問域名") 19
private String host;
// @ApiModelProperty("上傳成功后的回調設置")
private String callback;
// 忽略getter、setter方法
}
5、封裝上傳成功回調參數(shù)對象
當OSS上傳成功后,會根據(jù)該配置參數(shù)來回調對應接口
package org.pp.oss.model;
/**
* TODO oss上傳成功后的回調參數(shù)
*
* @author ss_419
* @version 1.0
* @date 2023/5/28 19:10
*/
public class OssCallbackParam {
//請求的回調地址
private String callbackUrl;
//回調是傳入request中的參數(shù)
private String callbackBody;
//回調時傳入?yún)?shù)的格式,比如表單提交形式
private String callbackBodyType;
public String getCallbackUrl() {
return callbackUrl;
}
public void setCallbackUrl(String callbackUrl) {
this.callbackUrl = callbackUrl;
}
public String getCallbackBody() {
return callbackBody;
}
public void setCallbackBody(String callbackBody) {
this.callbackBody = callbackBody;
}
public String getCallbackBodyType() {
return callbackBodyType;
}
public void setCallbackBodyType(String callbackBodyType) {
this.callbackBodyType = callbackBodyType;
}
}
6、封裝上傳成功后回調結果對象
回調接口中返回的數(shù)據(jù)對象,封裝了上傳文件的信息
/**
* TODO oss上傳文件的回調結果
*
* @author ss_419
* @version 1.0
* @date 2023/5/28 19:14
*/
public class OssCallbackResult {
private String filename;// 文件名稱
private String size;// 文件大小
private String mimeType;// 文件的mimeType
private String width;// 圖片文件的寬
private String height;// 圖片文件的高
// 忽略getter、setter方法
}
7、添加OSS業(yè)務接口OssService
/**
* TODO oss上傳管理Service
*
* @author ss_419
* @version 1.0
* @date 2023/5/28 19:16
*/
public interface OssService {
/**
* oss上傳策略生成
* @return
*/
OssPolicyResult policy();
/**
* oss上傳成功回調
* @param request
* @return
*/
OssCallbackResult callback(HttpServletRequest request);
}
8、OssService實現(xiàn)類
package org.pp.oss.service.impl;/*
package org.pp.oss.service.impl;
import org.pp.oss.model.OssCallbackResult;
import org.pp.oss.model.OssPolicyResult;
import org.pp.oss.service.OssService;
import javax.servlet.http.HttpServletRequest;
*/
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 org.pp.oss.model.OssCallbackParam;
import org.pp.oss.model.OssCallbackResult;
import org.pp.oss.model.OssPolicyResult;
import org.pp.oss.service.OssService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
/**
* TODO
*
* @author ss_419
* @version 1.0
* @date 2023/5/28 19:17
*/
@Service
public class OssServiceImpl implements OssService {
private static final Logger LOGGER = LoggerFactory.getLogger(OssServiceImpl.class);
@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;
/**
* 簽名生成
*
* @return
*/
@Override
public OssPolicyResult policy() {
OssPolicyResult result = new OssPolicyResult();
// 存儲目錄
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String baseDir = 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;
// 回調地址
OssCallbackParam callback = new OssCallbackParam();
callback.setCallbackUrl(ALIYUN_OSS_CALLBACK);
callback.setCallbackBody("filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
callback.setCallbackBody("application/x-www-form-urlencoded");
// 提交節(jié)點
String action = "https://" + 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, baseDir);
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(baseDir);
result.setCallback(callbackData);
result.setHost(action);
} catch (Exception e) {
LOGGER.error("簽名生成失敗{e}", e);
}
return result;
}
@Override
public OssCallbackResult callback(HttpServletRequest request) {
OssCallbackResult result = new OssCallbackResult();
String filename = request.getParameter("filename");
filename = "http://".concat(ALIYUN_OSS_BUCKET_NAME).concat(".").concat(ALIYUN_OSS_ENDPOINT).concat("/").concat(filename);
result.setFilename(filename);
result.setSize(request.getParameter("size"));
result.setMimeType(request.getParameter("mimeType"));
result.setHeight(request.getParameter("height"));
result.setWidth(request.getParameter("width"));
return result;
}
}
9、定義OssController接口
package org.pp.oss.controller;
import cn.hutool.json.JSONObject;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import org.pp.oss.model.OssCallbackResult;
import org.pp.oss.model.OssPolicyResult;
import org.pp.oss.service.OssService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* TODO Oss相關操作接口
*
* @author ss_419
* @version 1.0
* @date 2023/5/28 20:43
*/
@RestController
@RequestMapping("/aliyun/oss")
@CrossOrigin
public class AliyunOssController {
@Autowired
private OssService ossService;
@CrossOrigin
@RequestMapping("/policys")
public Map<String,String> policysMap(){
// 阿里云賬號AccessKey擁有所有API的訪問權限,風險很高。強烈建議您創(chuàng)建并使用RAM用戶進行API訪問或日常運維,請登錄RAM控制臺創(chuàng)建RAM用戶。
String accessId = "xxx";
String accessKey = "xxx";
// Endpoint以華東1(杭州)為例,其它Region請按實際情況填寫。
String endpoint = "oss-cn-shanghai.aliyuncs.com";
// 填寫B(tài)ucket名稱,例如examplebucket。
String bucket = "xxx";
// 填寫Host地址,格式為https://bucketname.endpoint。
String host = "https://" + bucket + "."+ endpoint;
// 設置上傳回調URL,即回調服務器地址,用于處理應用服務器與OSS之間的通信。OSS會在文件上傳完成后,把文件上傳信息通過此回調URL發(fā)送給應用服務器。
// String callbackUrl = "https://192.168.0.0:8888";
// 設置上傳到OSS文件的前綴,可置空此項。置空后,文件將上傳至Bucket的根目錄下。
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String formatData = dateFormat.format(new Date());
String dir = "osstest/"+formatData+ "/";
// 創(chuàng)建ossClient實例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessId, accessKey);
try {
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);
String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes("utf-8");
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = ossClient.calculatePostSignature(postPolicy);
Map<String, String> 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));
return respMap;
// respMap.put("expire", formatISO8601Date(expiration));
// 回調數(shù)據(jù)
// 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());
}
return null;
}
/**
* oss上傳簽名生成
* @return
*/
@CrossOrigin
@RequestMapping("/policy")
public OssPolicyResult policy(){
OssPolicyResult result = ossService.policy();
System.out.println("result = " + result);
return result;
}
/**
* oss上傳成功回調
* @return
*/
@RequestMapping("/callback")
public OssCallbackResult callback(HttpServletRequest request){
OssCallbackResult callback = ossService.callback(request);
System.out.println("callback = " + callback);
return callback;
}
}
對接口進行測試,如下圖所示,請求返回了oss文件上傳時所需的對應參數(shù)
4、Vue文件上傳測試代碼
這里為了更加方便快捷的進行文件上傳接口的測試,我選擇使用Vue+Element-Ui來搭建一個簡單的上傳案例
1、創(chuàng)建Vue項目
在控制臺中輸入vue ui,啟動vue項目圖形管理界面
訪問http://localhost:8000 ,進入如下圖操作界面即代表啟動成功
找到項目管理器,創(chuàng)建一個新Vue項目
這里選擇Vue2版本
創(chuàng)建成功后添加本次案例所需要的依賴:
- axios:用于對后端服務發(fā)起Ajax請求
- element-ui:本案例使用到該ui組件庫中的Upload,用于文件上傳
在Vue項目中的main.js中啟用對應依賴
import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import axios from "axios";
import VueAxios from "vue-axios";
import router from './router'
import store from './store'
Vue.config.productionTip = false
// Vue.use(axios)
Vue.use(VueAxios,axios)
Vue.use(ElementUI);
new Vue({
router,
store,
render: function (h) { return h(App) }
}).$mount('#app')
創(chuàng)建OssUpload組件,該組件可以在項目中引用
<template>
<el-upload
class="upload-demo"
:action="objData.host"
:before-upload="ossPolicy"
:data="objData"
:file-list="fileList"
list-type="picture">
<el-button size="small" type="primary">點擊上傳</el-button>
<div slot="tip" class="el-upload__tip">只能上傳jpg/png文件,且不超過500kb</div>
</el-upload>
</template>
<script>
export default {
data() {
return {
fileList: [],
objData: {
OSSAccessKeyId: '',
policy: '',
signature: '',
key: '',
host: '',
dir: ''
}
};
},
methods: {
ossPolicy(file) {
let _self = this;
// 在上傳前 進行服務器簽名
return new Promise((resolve, reject) => {
this.axios.get("http://localhost:8080/aliyun/oss/policy")
.then(response => {
console.log(response)
_self.objData.OSSAccessKeyId = response.data.accessKeyId
_self.objData.policy = response.data.policy
_self.objData.signature = response.data.signature
_self.objData.dir = response.data.dir
_self.objData.host = response.data.host+''
_self.objData.key = response.data.dir + "${filename}"
resolve(true) // 繼續(xù)上傳
})
.catch(error => {
console.log(error)
reject(false)
})
}
)
}
}
}
</script>
<style>
</style>
在HelloWorld.vue中引用文件上傳組件
```js
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<OssUpload></OssUpload>
</div>
</template>
<script>
// 引用組件
import OssUpload from "@/components/OssUpload.vue";
export default {
name: 'HelloWorld',
components: {OssUpload},
props: {
msg: String
}
}
</script>
<style >
</style>
前后端聯(lián)調
-
啟動后端服務
-
啟動前端項目
選擇文件進行上傳,如下圖所示即表示上傳成功
查看對應的OSSBucket,圖片已成功存儲至OSS服務中文章來源:http://www.zghlxwxcb.cn/news/detail-465777.html
項目地址文章來源地址http://www.zghlxwxcb.cn/news/detail-465777.html
到了這里,關于SpringBoot整合OSS文件上傳的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!