SpringBoot整合OSS文件上传
Posted atwood-pan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot整合OSS文件上传相关的知识,希望对你有一定的参考价值。
一、注册阿里云账号并开通OSS服务
1、登录阿里云账号
2、创建一个bucket
3、创建子用户
对自用户分配权限,打开操作OSS的全部权限(也可根据业务需求进行更改)
4、配置上传跨域规则
- 任何来源: *
- 允许方法: POST
- 任何请求头Headers: *
二、文件上传方式
1、服务器直传方式
每个OSS的用户都会用到上传服务。Web端常见的上传方法是用户在浏览器或App端上传文件到应用服务器,应用服务器再把文件上传到OSS
和数据直传到OSS相比,以上方法有三个缺点:
- 上传慢:用户数据需先上传到到应用服务器,之后再上传到OSS。网络传输时间比直传到OSS多一倍。如果用于数据不通过应用服务器中转,而是直传到OSS,速度将大大提升。而且OSS采用BGP带宽,能保证各地各运营商之间的传输速度
- 扩展性差:如果后续用户多了,应用服务器会成为瓶颈
- 费用高:需要准备多台应用服务器。由于OSS上传流量是免费的,如果数据直传到OSS,不通过应用服务器,那么将能省下几台应用服务器
2、服务端签名后前端直传
Web前端服务端请求签名,然后前端(Vue)直接上传,不会对服务端产生压力,而且安全可靠。
相关资料:服务端签名直传并设置上传回调概述
Java连接实例:Java实践OSS
上传回调流程
- Web前端请求应用服务器,获取上传所需参数(如OSS的accessKeyId、policy、callback等参数)
- 应用服务器返回相关参数
- Web前端直接向OSS服务发起上传文件请求
- 等上传完成后OSS服务会回调应用服务器的回调接口
- 应用服务器返回响应给OSS服务
- OSS服务将应用服务器回调接口的内容返回给Web前端
3、SpringBoot整合OSS实现文件上传
1、在pom.xml中添加相关依赖
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
2、修改SpringBoot配置文件
#操作oss需要的一些参数
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、封装前端上传策略返回对象
前端直传时所需要的参数
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、封装上传成功回调参数对象
当OSS上传成功后,会根据该配置参数来回调对应接口
package org.pp.oss.model;
/**
* TODO oss上传成功后的回调参数
*
* @author ss_419
* @version 1.0
* @date 2023/5/28 19:10
*/
public class OssCallbackParam
//请求的回调地址
private String callbackUrl;
//回调是传入request中的参数
private String callbackBody;
//回调时传入参数的格式,比如表单提交形式
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、封装上传成功后回调结果对象
回调接口中返回的数据对象,封装了上传文件的信息
/**
* 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业务接口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实现类
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");
// 提交节点
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的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessId = "xxx";
String accessKey = "xxx";
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "oss-cn-shanghai.aliyuncs.com";
// 填写Bucket名称,例如examplebucket。
String bucket = "xxx";
// 填写Host地址,格式为https://bucketname.endpoint。
String host = "https://" + bucket + "."+ endpoint;
// 设置上传回调URL,即回调服务器地址,用于处理应用服务器与OSS之间的通信。OSS会在文件上传完成后,把文件上传信息通过此回调URL发送给应用服务器。
// 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+ "/";
// 创建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));
// 回调数据
// 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文件上传时所需的对应参数
4、Vue文件上传测试代码
这里为了更加方便快捷的进行文件上传接口的测试,我选择使用Vue+Element-Ui来搭建一个简单的上传案例
1、创建Vue项目
在控制台中输入vue ui,启动vue项目图形管理界面
访问http://localhost:8000 ,进入如下图操作界面即代表启动成功
找到项目管理器,创建一个新Vue项目
这里选择Vue2版本
创建成功后添加本次案例所需要的依赖:
- axios:用于对后端服务发起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\')
创建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) // 继续上传
)
.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>
前后端联调
-
启动后端服务
-
启动前端项目
选择文件进行上传,如下图所示即表示上传成功
查看对应的OSSBucket,图片已成功存储至OSS服务中
PassJava 开源(十三) : Spring Cloud 整合 OSS 对象存储 #私藏项目实操分享#
PassJava (佳必过) 项目全套学习教程连载中,关注公众号第一时间获取。
文档在线地址:www.passjava.cn
整合OSS对象存储
一、缘起
每个 OSS 的用户都会用到上传服务。Web 端常见的上传方法是用户在浏览器或 APP 端上传文件到应用服务器,应用服务器再把文件上传到 OSS。具体流程如下图所示。
和数据直传到 OSS 相比,以上方法有三个缺点:
- 上传慢:用户数据需先上传到应用服务器,之后再上传到OSS。网络传输时间比直传到OSS多一倍。如果用户数据不通过应用服务器中转,而是直传到OSS,速度将大大提升。而且OSS采用BGP带宽,能保证各地各运营商之间的传输速度。
- 扩展性差:如果后续用户多了,应用服务器会成为瓶颈。
- 费用高:需要准备多台应用服务器。由于OSS上传流量是免费的,如果数据直传到OSS,不通过应用服务器,那么将能省下几台应用服务器。
二、技术方案
服务端签名后直传
背景
采用JavaScript客户端直接签名(参见JavaScript客户端签名直传)时,AccessKeyID和AcessKeySecret会暴露在前端页面,因此存在严重的安全隐患。因此,OSS提供了服务端签名后直传的方案。
原理介绍
服务端签名后直传的原理如下:
- 用户发送上传Policy请求到应用服务器。
- 应用服务器返回上传Policy和签名给用户。
- 用户直接上传数据到OSS。
三、实现案例
1.开通阿里云OSS
-
创建Bucket 存储桶
- 获取accesskey id和secret
-
分配权限
分配 管理对象存储服务(OSS)权限
2.使用OSS SDK
1) 安装SDK
在Maven项目中加入依赖项
https://help.aliyun.com/document_detail/32009.html?spm=a2c4g.11186623.6.769.2c5145dc4TUgTa
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.8.0</version>
</dependency>
2) 上传文件到OSS
@Test
void testUploadByOss() throws FileNotFoundException
// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "http://oss-cn-beijing.aliyuncs.com";
// 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
String accessKeyId = "xxxx";
String accessKeySecret = "xxxx";
String bucketName = "passjava";
// <yourObjectName>上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。
String localFile = "C:\\\\Users\\\\Administrator\\\\Pictures\\\\coding_java.png";
String fileKeyName = "coding_java.png";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
InputStream inputStream = new FileInputStream(localFile);
ossClient.putObject(bucketName, fileKeyName, inputStream);
// 关闭OSSClient。
ossClient.shutdown();
3.整合Spring Cloud Alicloud OSS
1) passjava-common项目引入spring-cloud-starter-alicloud-oss依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
</dependency>
2) 配置alicloud oss
spring:
cloud:
alicloud:
access-key: xxxx
secret-key: xxxx
oss:
endpoint: oss-cn-beijing.aliyuncs.com
3)测试上传
@Autowired
OSSClient ossClient;
@Test
void testUploadByAlicloudOss() throws FileNotFoundException
String bucketName = "passjava";
String localFile = "C:\\\\Users\\\\Administrator\\\\Pictures\\\\coding_java.png";
String fileKeyName = "coding_java.png";
InputStream inputStream = new FileInputStream(localFile);
ossClient.putObject(bucketName, fileKeyName, inputStream);
ossClient.shutdown();
4.获取服务端签名
4.1 准备工作:
- 创建一个第三方服务passjava-thirdparty
- 引入passjava-common模块,并且排除mybatis-plus依赖
<dependency>
<groupId>com.jackson0714.passjava</groupId>
<artifactId>passjava-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
- 配置服务发现和端口
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
application:
name: passjava-thirdparty
server:
port: 14000
- 配置配置中心
spring.application.name=passjava-thirdparty
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=passjava-thirdparty
spring.cloud.nacos.config.extension-configs[0].data-id=oss.yml
spring.cloud.nacos.config.extension-configs[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-configs[0].refresh=true
- 配置Nacos命名空间和oss.yml
spring:
cloud:
alicloud:
access-key: LTAI4G3KxBJ26EUbWsenmqhP
secret-key: RHtADVlvlKJvVBQnFNNvnne9p4NwnA
oss:
endpoint: oss-cn-beijing.aliyuncs.com
- 开启服务发现
@EnableDiscoveryClient
@EnableDiscoveryClient
@SpringBootApplication
public class PassjavaThirdpartyApplication
public static void main(String[] args)
SpringApplication.run(PassjavaThirdpartyApplication.class, args);
4.2 获取签名类
@RestController
@RequestMapping("/thirdparty/v1/admin/oss")
public class OssController
@Autowired
OSS ossClient;
@Value("$spring.cloud.alicloud.access-key")
private String accessId;
@Value("$spring.cloud.alicloud.secret-key")
private String accessKey;
@Value("$spring.cloud.alicloud.oss.endpoint")
private String endpoint;
@Value("$spring.cloud.alicloud.oss.bucket")
private String bucket;
@RequestMapping("/getPolicy")
public Map<String, String> getPolicy()
String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
// callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
// String callbackUrl = "http://88.88.88.88:8888";
String formatDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
String dir = formatDate + "/"; // 用户上传文件时指定的前缀。
Map<String, String> respMap = new LinkedHashMap<String, String>();
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);
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));
catch (Exception e)
// Assert.fail(e.getMessage());
System.out.println(e.getMessage());
finally
ossClient.shutdown();
return respMap;
测试接口
http://localhost:14000/api/thirdparty/v1/admin/oss/getPolicy
"accessid": "LTAI4G3KxBJ26EUbWsenmqhP",
"policy": "eyJleHBpcmF0aW9uIjoiMjAyMC0wNC0yOFQwMjozMzowNy42NzNaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjAwMF0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCIyMDIwLTA0LTI4LyJdXX0=",
"signature": "pfn4cggFTMMNqTs+qUnDN5c+k5M=",
"dir": "2020-04-28/",
"host": "https://passjava.oss-cn-beijing.aliyuncs.com",
"expire": "1588041187"
4.3 配置网关路由
因为前端页面配置的统一访问路径是http://localhost:8060/api/,所以需要将访问thirdparty的服务通过网关路由到thirdparty服务
将请求
http://localhost:8060/api/thirdparty/v1/admin/oss/getPolicy
转发到
http://localhost:14000/api/thirdparty/v1/admin/oss/getPolicy
配置网关:
spring:
cloud:
gateway:
routes:
- id: route_thirdparty # 题目微服务路由规则
uri: lb://passjava-thirdparty # 负载均衡,将请求转发到注册中心注册的assjava-thirdparty服务
predicates: # 断言
- Path=/api/thirdparty/** # 如果前端请求路径包含 api/thirdparty,则应用这条路由规则
filters: #过滤器
- RewritePath=/api/(?<segment>.*),/$\\segment # 将跳转路径中包含的api替换成空
测试可以上传成功
4.4 配置跨域访问
配置跨域访问,所有post请求都可以跨域访问
4.5 Web端上传组件
- 单文件上传组件
singleUpload.vue
<template>
<div>
<el-upload
action="http://passjava.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 :src="fileList[0].url" >
</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: ,
// callback:,
,
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.policy;
_self.dataObj.signature = response.data.signature;
_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;
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>
- 获取签名的JS文件
import http from @/utils/httpRequest.js
export function policy ()
return new Promise((resolve) =>
http(
url: http.adornUrl(/thirdparty/v1/admin/oss/getPolicy),
method: get,
params: http.adornParams()
).then(( data ) =>
resolve(data)
)
)
- 使用单文件上传组件
使用上传图片组件
<el-form-item label="类型logo路径" prop="logoUrl">
<single-upload v-model="dataForm.logoUrl"></single-upload>
</el-form-item>
<script>
import SingleUpload from "@/components/upload/singleUpload" // 引入单文件上传组件
export default
components: SingleUpload
</script>
上传文件成功
下节预告
- 数据校验
代码地址
https://github.com/Jackson0714/PassJava-Platform
文档在线地址:http://www.passjava.cn
以上是关于SpringBoot整合OSS文件上传的主要内容,如果未能解决你的问题,请参考以下文章
PassJava 开源(十三) : Spring Cloud 整合 OSS 对象存储 #私藏项目实操分享#