华为云OBS的官方文档(链接:https://support.huaweicloud.com/sdk-java-devg-obs/obs_21_0901.html#section1)中关于上传文件的内容,只提供了使用JAVA获取临时上传链接,并使用JAVA创建请求上传纯文本的方法。想要把这部分内容应用到 SpringBoot + Vue + ElementUI/Element-Plus 中,还差很多东西。
文章目录
- 0 前提条件
- 1 OBS 桶创建和配置
- 1.1 华为云OBS桶的创建
- 1.2 配置桶允许跨域请求
- 1.3 获取桶信息
- 2 SpringBoot 后端配置
- 2.1 依赖
- 2.2 application.properties 配置
- 2.3 工具类
- 2.4 Controller
- 3 Vue 前端配置
- 3.1 Vue 组件
- 3.2 upload API
- 3.3 request.js
0 前提条件
请先确保SpringBoot、Vue、ElementUI/Element-Plus、axios 等工具安装和配置正确
笔者使用环境:SpringBoot 3.1.0, Vue 3, Element-Plus
SpringBoot 2.7 和 Vue 2 按理不会有很大区别,如有需要请自行调整代码
1 OBS 桶创建和配置
1.1 华为云OBS桶的创建
可参考如下配置
1.2 配置桶允许跨域请求
可参考官方文档:https://support.huaweicloud.com/sdk-browserjs-devg-obs/obs_24_0201.html
其中允许的来源设置为 * 即允许所有跨域请求,也可按如下设置,仅允许当前本地前端访问,其中 8080 为 Vue 前端端口:
http://localhost:8080
http://127.0.0.1:8080
补充头域 可留空
1.3 获取桶信息
后边需要用到的信息有:bucketName、accessKeyId、securitAccessKey、endPoint
bucketName: 本文1.1中创建桶时自定义的桶名称;
accessKeyId 和 securitAccessKey: 参考官方文档https://support.huaweicloud.com/usermanual-ca/zh-cn_topic_0046606340.html;
endPoint:参考下图
2 SpringBoot 后端配置
2.1 依赖
<dependency><groupId>com.huaweicloud</groupId><artifactId>esdk-obs-java</artifactId> <!-- 华为云依赖 --><version>3.22.12</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId> <!-- log日志 --><optional>true</optional></dependency>
2.2 application.properties 配置
application.properties 添加如下配置,值为本文1.3获取的桶信息
huaweicloud.obs.accessKey=
huaweicloud.obs.securityKey=
huaweicloud.obs.endPoint=
huaweicloud.obs.bucketName=
huaweicloud.obs.path =
2.3 工具类
在 com.gabriel.docsharing.utils
创建如下工具类:
package com.gabriel.docsharing.utils;import com.obs.services.ObsClient;
import com.obs.services.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.util.HashMap;
import java.util.Map;@Slf4j
@Component
public class HuaweiOBS {@Value("${huaweicloud.obs.accessKey}")private String ak;@Value("${huaweicloud.obs.securityKey}")private String sk;@Value("${huaweicloud.obs.bucketName}")private String bucketName;@Value("${huaweicloud.obs.endPoint}")private String endpoint;// 文件目录private final String prifix = "/test";/*** 获取上传地址** @param fileName 文件名称* @param fileType 文件路径* @return*/public String getUploadUrl(String fileName, FileType fileType) {try {// 创建ObsClient实例ObsClient obsClient = new ObsClient(ak, sk, endpoint);// URL有效期,3600秒long expireSeconds = 3600L;Map<String, String> headers = new HashMap<String, String>();headers.put("Content-Type", "application/octet-stream");String objectName = fileType.getType().concat("/").concat(fileName);TemporarySignatureRequest request = new TemporarySignatureRequest(HttpMethodEnum.PUT, expireSeconds);request.setBucketName(bucketName);request.setObjectKey(objectName);request.setHeaders(headers);TemporarySignatureResponse response = obsClient.createTemporarySignature(request);return response.getSignedUrl();} catch (Exception e) {log.error("获取上传地址异常:{}", e.getMessage(), e);}return null;}public enum FileType {TEST("test", "测试"),PDF("pdf","PDF文件");private String type;private String desc;FileType(String type, String desc) {this.type = type;this.desc = desc;}public String getType() {return type;}public String getDesc() {return desc;}}
}
2.4 Controller
在 com.gabriel.docsharing.controller
创建如下 Controller:
package com.gabriel.docsharing.controller;import com.gabriel.docsharing.utils.HuaweiOBS;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;/*** 前端控制器* * @author Gabriel* @since 2023-06-08*/
@Log
@RestController
@RequestMapping("/doc")
public class DocController {@AutowiredHuaweiOBS huaweiOBS;@RequestMapping(value = "/getUploadUrl", method = RequestMethod.GET)public String getUploadUrl(String filename){String url = huaweiOBS.getUploadUrl(filename, HuaweiOBS.FileType.TEST);log.info("get upload url, filename: "+ filename + " result: " + url);return url;}
}
3 Vue 前端配置
3.1 Vue 组件
创建 Upload.vue 文件(请自行设置路由),内容如下:
<template><el-upload class="upload" ref="upload" drag:http-request="uploadAction":limit="1":auto-upload="false":on-change="fileChange":on-exceed="handleExceed"><div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div></el-upload><el-button @click="submitForm">上传</el-button>
</template><script>
import {genFileId} from "element-plus";
import {useUploadApi} from "@/api/upload";export default {name: "Upload",data() {return {uploadUrl: ''}},methods: {fileChange(file) { // 上传文件发生变化时,根据新文件获取上传链接if (!this.checkDoc(file)) {this.$refs.upload.clearFiles();} else {useUploadApi().getUploadUrl(file.name).then((res) => {this.uploadUrl = res;});}},handleExceed(files) { // 上传第二个文件时,覆盖第一个文件if (this.checkDoc(files[0])) {this.$refs.upload.clearFiles()let file = files[0]file.uid = genFileId()this.$refs.upload.handleStart(file)}},checkDoc(file) {// 文件大小和格式检查// let index = file.name.lastIndexOf(".");// let extension = file.name.substr(index + 1);// let extensionList = ["jpeg"];// const isLt2M = file.size / 1024 / 1024 < 1;// if (!isLt2M) {// ElMessage.error("文件不可超出1M");// return false;// } else if (extensionList.indexOf(extension) < 0) {// ElMessage.error("当前文件格式不支持");// return false;// } else {// return true;// }return true;},submitForm() { // 提交上传this.$refs.upload.submit();},uploadAction(param){ // 提交时的自定义上传配置useUploadApi().uploadFile(this.uploadUrl, param.file).then(res=>{alert("上传完成,请在检查中查看返回状态")})},},
}
</script>
3.2 upload API
创建 api/upload/index.js 文件,内容如下:
import request from '@/utils/request';/*** 上传文件api接口集合* @method signIn 用户登录* @method signOut 用户退出登录*/
export function useUploadApi() {return {getUploadUrl: (filename) => {return request({url: '/api/doc/getUploadUrl?filename=' + filename,method: 'get'});},uploadFile: (url, file) => {return request({url: url,method: 'put',headers:{'Content-Type': 'application/octet-stream'},data: file});}};
}
3.3 request.js
创建 utils/request.js 文件,内容如下:
import axios from 'axios';// 创建 axios 实例
const service = axios.create({baseURL: process.env.VUE_APP_BASE_API,timeout: 50000,
});export default service;