大家好,我是雄雄,歡迎關注微信公衆号:雄雄的小課堂。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL4Q2Y1YGNyMWZkNGO0AzM4UGM2QzY4UWOhF2M3Y2NmJ2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
前言
jeecg-boot
架構中,其實對接的功能還是挺多的,其中就有檔案雲存儲伺服器,不過是阿裡雲
oss
的,那如果我們使用的是七牛雲,或者華為雲obs呢?我們需要改哪些内容才能實作上傳
obs
的目的呢,今天我們就來看看如何使用
jeecg-boot
來實作将檔案(圖檔)上傳到華為雲
obs
中。
配置nacos
因為我們用的是微服務版本,是以配置都在
nacos
中,如果是普通的
boot
版本的話,直接在
yml
檔案中寫配置就行。
nacos
的配置如下:
- 找到
節點,修改jeecg
的值:uploadType
uploadType: hwobs
記住這個hwobs的值,我們需要在代碼中聲明一下它,相當于一個變量,這個值必須和代碼中聲明的那個變量的值一樣,不然就找不到了。
- 添加obs節點:
#華為雲oss存儲配置
obs:
endpoint: obs.cn-xxxxx-9.myhuaweicloud.com
accessKey: KD6BYxxxxxx
secretKey: Zv83xxxxxx
bucketName: xxxxx
staticDomain: xxxxx.obs.cn-xxxxxx-9.myhuaweicloud.com
注意:對應的值需要改成你自己的ak、sk等。
修改POM檔案,添加華為雲obs的依賴
添加代碼如下:
<!--華為雲OBS-->
<dependency>
<groupId>com.huaweicloud</groupId>
<artifactId>esdk-obs-java</artifactId>
<version>3.21.8</version>
<exclusions>
<exclusion>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</exclusion>
</exclusions>
</dependency>
建立OBS工具類ObsBootUtil
package org.jeecg.common.util.oss;
import com.obs.services.ObsClient;
import com.obs.services.model.ObsObject;
import com.obs.services.model.PutObjectResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.FileItemStream;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.common.util.filter.FileTypeFilter;
import org.jeecg.common.util.filter.StrAttackFilter;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.UUID;
/**
* @Description: 華為雲 oss 上傳工具類(高依賴版)
* @Date: 2019/5/10
* @author: jeecg-boot
*/
@Slf4j
public class ObsBootUtil {
private static String endPoint;
private static String accessKeyId;
private static String accessKeySecret;
private static String bucketName;
/**
* oss 工具用戶端
*/
private static ObsClient ossClient = null;
public static String getEndPoint() {
return endPoint;
}
public static void setEndPoint(String endPoint) {
ObsBootUtil.endPoint = endPoint;
}
public static String getAccessKeyId() {
return accessKeyId;
}
public static void setAccessKeyId(String accessKeyId) {
ObsBootUtil.accessKeyId = accessKeyId;
}
public static String getAccessKeySecret() {
return accessKeySecret;
}
public static void setAccessKeySecret(String accessKeySecret) {
ObsBootUtil.accessKeySecret = accessKeySecret;
}
public static String getBucketName() {
return bucketName;
}
public static void setBucketName(String bucketName) {
ObsBootUtil.bucketName = bucketName;
}
public static ObsClient getOssClient() {
return ossClient;
}
/**
* 上傳檔案至華為雲 OBS
* 檔案上傳成功,傳回檔案完整通路路徑
* 檔案上傳失敗,傳回 null
*
* @param file 待上傳檔案
* @param fileDir 檔案儲存目錄
* @return oss 中的相對檔案路徑
*/
public static String upload(MultipartFile file, String fileDir, String customBucket) throws Exception {
//update-begin-author:liusq date:20210809 for: 過濾上傳檔案類型
FileTypeFilter.fileTypeFilter(file);
//update-end-author:liusq date:20210809 for: 過濾上傳檔案類型
String filePath;
initOss(endPoint, accessKeyId, accessKeySecret);
StringBuilder fileUrl = new StringBuilder();
String newBucket = bucketName;
if (oConvertUtils.isNotEmpty(customBucket)) {
newBucket = customBucket;
}
try {
//判斷桶是否存在,不存在則建立桶
if (!ossClient.headBucket(newBucket)) {
ossClient.createBucket(newBucket);
}
// 擷取檔案名
String orgName = file.getOriginalFilename();
if ("".equals(orgName) || orgName == null) {
orgName = file.getName();
}
orgName = CommonUtils.getFileName(orgName);
String fileName = !orgName.contains(".")
? orgName + "_" + System.currentTimeMillis()
: orgName.substring(0, orgName.lastIndexOf("."))
+ "_" + System.currentTimeMillis()
+ orgName.substring(orgName.lastIndexOf("."));
if (!fileDir.endsWith(SymbolConstant.SINGLE_SLASH)) {
fileDir = fileDir.concat(SymbolConstant.SINGLE_SLASH);
}
//update-begin-author:wangshuai date:20201012 for: 過濾上傳檔案夾名特殊字元,防止攻擊
fileDir = StrAttackFilter.filter(fileDir);
//update-end-author:wangshuai date:20201012 for: 過濾上傳檔案夾名特殊字元,防止攻擊
fileUrl.append(fileDir).append(fileName);
filePath = "https://" + newBucket + "." + endPoint + SymbolConstant.SINGLE_SLASH + fileUrl;
PutObjectResult result = ossClient.putObject(newBucket, fileUrl.toString(), file.getInputStream());
// 設定權限(公開讀)
// ossClient.setBucketAcl(newBucket, CannedAccessControlList.PublicRead);
if (result != null) {
log.info("------OSS檔案上傳成功------" + fileUrl);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return filePath;
}
/**
* 檔案上傳
*
* @param file 檔案
* @param fileDir fileDir
* @return 路徑
*/
public static String upload(MultipartFile file, String fileDir) throws Exception {
return upload(file, fileDir, null);
}
/**
* 上傳檔案至華為雲 OBS
* 檔案上傳成功,傳回檔案完整通路路徑
* 檔案上傳失敗,傳回 null
*
* @param file 待上傳檔案
* @param fileDir 檔案儲存目錄
* @return oss 中的相對檔案路徑
*/
public static String upload(FileItemStream file, String fileDir) {
String filePath;
initOss(endPoint, accessKeyId, accessKeySecret);
StringBuilder fileUrl = new StringBuilder();
try {
String suffix = file.getName().substring(file.getName().lastIndexOf('.'));
String fileName = UUID.randomUUID().toString().replace("-", "") + suffix;
if (!fileDir.endsWith(SymbolConstant.SINGLE_SLASH)) {
fileDir = fileDir.concat(SymbolConstant.SINGLE_SLASH);
}
fileDir = StrAttackFilter.filter(fileDir);
fileUrl.append(fileDir).append(fileName);
filePath = "https://" + bucketName + "." + endPoint + SymbolConstant.SINGLE_SLASH + fileUrl;
PutObjectResult result = ossClient.putObject(bucketName, fileUrl.toString(), file.openStream());
// 設定權限(公開讀)
//ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
if (result != null) {
log.info("------OSS檔案上傳成功------" + fileUrl);
}
} catch (IOException e) {
e.printStackTrace();
return null;
}
return filePath;
}
/**
* 删除檔案
*
* @param url 路徑
*/
public static void deleteUrl(String url) {
deleteUrl(url, null);
}
/**
* 删除檔案
*
* @param url 路徑
*/
public static void deleteUrl(String url, String bucket) {
String newBucket = bucketName;
if (oConvertUtils.isNotEmpty(bucket)) {
newBucket = bucket;
}
String bucketUrl = "https://" + newBucket + "." + endPoint + SymbolConstant.SINGLE_SLASH;
//TODO 暫時不允許删除雲存儲的檔案
//initOss(endPoint, accessKeyId, accessKeySecret);
url = url.replace(bucketUrl, "");
ossClient.deleteObject(newBucket, url);
}
/**
* 删除檔案
*
* @param fileName 檔案名稱
*/
public static void delete(String fileName) {
ossClient.deleteObject(bucketName, fileName);
}
/**
* 擷取檔案流
*
* @param objectName 對象名
* @param bucket 桶
* @return 檔案流
*/
public static InputStream getOssFile(String objectName, String bucket) {
InputStream inputStream = null;
try {
String newBucket = bucketName;
if (oConvertUtils.isNotEmpty(bucket)) {
newBucket = bucket;
}
initOss(endPoint, accessKeyId, accessKeySecret);
//update-begin---author:liusq Date:20220120 for:替換objectName字首,防止key不一緻導緻擷取不到檔案----
objectName = ObsBootUtil.replacePrefix(objectName, bucket);
//update-end---author:liusq Date:20220120 for:替換objectName字首,防止key不一緻導緻擷取不到檔案----
ObsObject ossObject = ossClient.getObject(newBucket, objectName);
inputStream = new BufferedInputStream(ossObject.getObjectContent());
} catch (Exception e) {
log.info("檔案擷取失敗" + e.getMessage());
}
return inputStream;
}
/**
* 擷取檔案外鍊
*
* @param bucketName 桶名稱
* @param objectName 對項名
* @param expires 日期
* @return 外鍊
*/
public static String getObjectUrl(String bucketName, String objectName, Date expires) {
initOss(endPoint, accessKeyId, accessKeySecret);
try {
//update-begin---author:liusq Date:20220120 for:替換objectName字首,防止key不一緻導緻擷取不到檔案----
objectName = ObsBootUtil.replacePrefix(objectName, bucketName);
//update-end---author:liusq Date:20220120 for:替換objectName字首,防止key不一緻導緻擷取不到檔案----
if (ossClient.doesObjectExist(bucketName, objectName)) {
//URL url = ossClient.generatePresignedUrl(bucketName, objectName, expires);
//log.info("原始url : {}", url.toString());
//log.info("decode url : {}", URLDecoder.decode(url.toString(), "UTF-8"));
//【issues/4023】問題 oss外鍊經過轉編碼後,部分無效,大概在三分一;無需轉編碼直接傳回即可 #4023
//return url.toString();
return "";
}
} catch (Exception e) {
log.info("檔案路徑擷取失敗" + e.getMessage());
}
return null;
}
/**
* 初始化 oss 用戶端
*/
private static void initOss(String endpoint, String accessKeyId, String accessKeySecret) {
if (ossClient == null) {
ossClient = new ObsClient(accessKeyId, accessKeySecret, endpoint);
}
}
/**
* 上傳檔案到oss
*
* @param stream 檔案流
* @param relativePath 相對路徑
* @return 檔案路徑
*/
public static String upload(InputStream stream, String relativePath) {
String filePath = "https://" + bucketName + "." + endPoint + SymbolConstant.SINGLE_SLASH + relativePath;
initOss(endPoint, accessKeyId, accessKeySecret);
PutObjectResult result = ossClient.putObject(bucketName, relativePath, stream);
// 設定權限(公開讀)
//ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
if (result != null) {
log.info("------OSS檔案上傳成功------" + relativePath);
}
return filePath;
}
/**
* 替換字首,防止key不一緻導緻擷取不到檔案
*
* @param objectName 檔案上傳路徑 key
* @param customBucket 自定義桶
* @return 對象名
* @date 2022-01-20
* @author lsq
*/
private static String replacePrefix(String objectName, String customBucket) {
log.info("------replacePrefix---替換前---objectName:{}", objectName);
String newBucket = bucketName;
if (oConvertUtils.isNotEmpty(customBucket)) {
newBucket = customBucket;
}
String path = "https://" + newBucket + "." + endPoint + SymbolConstant.SINGLE_SLASH;
objectName = objectName.replace(path, "");
log.info("------replacePrefix---替換後---objectName:{}", objectName);
return objectName;
}
public static String getOriginalUrl(String url) {
return url;
}
}
建立OBS配置類
代碼如下:
package org.jeecg.config.oss;
import org.jeecg.common.util.oss.ObsBootUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 華為雲存儲 配置
*
* @author: jeecg-boot
*/
@Configuration
public class ObsConfig {
@Value("${jeecg.obs.endpoint}")
private String endpoint;
@Value("${jeecg.obs.accessKey}")
private String accessKeyId;
@Value("${jeecg.obs.secretKey}")
private String accessKeySecret;
@Value("${jeecg.obs.bucketName}")
private String bucketName;
@Bean
public void initObsBootConfig() {
ObsBootUtil.setEndPoint(endpoint);
ObsBootUtil.setAccessKeyId(accessKeyId);
ObsBootUtil.setAccessKeySecret(accessKeySecret);
ObsBootUtil.setBucketName(bucketName);
}
}
聲明配置變量
在
CommonConstant
接口中聲明在
nacos
中配置的變量:
String UPLOAD_TYPE_OBS = "hwobs";
修改原來檔案上傳的方法
首先找到類
CommonUtils
,的
uploadOnlineImage
方法,修改成如下:
public static String uploadOnlineImage(byte[] data, String basePath, String bizPath, String uploadType) {
String dbPath = null;
String fileName = "image" + Math.round(Math.random() * 100000000000L);
fileName += "." + PoiPublicUtil.getFileExtendName(data);
try {
if (CommonConstant.UPLOAD_TYPE_LOCAL.equals(uploadType)) {
File file = new File(basePath + File.separator + bizPath + File.separator);
if (!file.exists()) {
file.mkdirs();// 建立檔案根目錄
}
String savePath = file.getPath() + File.separator + fileName;
File savefile = new File(savePath);
FileCopyUtils.copy(data, savefile);
dbPath = bizPath + File.separator + fileName;
} else {
InputStream in = new ByteArrayInputStream(data);
String relativePath = bizPath + "/" + fileName;
if (CommonConstant.UPLOAD_TYPE_MINIO.equals(uploadType)) {
dbPath = MinioUtil.upload(in, relativePath);
} else if (CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType)) {
dbPath = OssBootUtil.upload(in, relativePath);
} else {
dbPath = ObsBootUtil.upload(in, relativePath);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return dbPath;
}
修改
upload
方法:
/**
* 統一全局上傳
*
* @Return: java.lang.String
*/
public static String upload(MultipartFile file, String bizPath, String uploadType) {
String url = "";
try {
if (CommonConstant.UPLOAD_TYPE_MINIO.equals(uploadType)) {
url = MinioUtil.upload(file, bizPath);
} else if (CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType)) {
url = OssBootUtil.upload(file, bizPath);
}else{
url = ObsBootUtil.upload(file, bizPath);
}
} catch (Exception exception) {
exception.printStackTrace();
}
return url;
}
修改
OssFileServiceImpl
實作類的
upload
方法(當然你新寫一個也行):
/**
* @Description: OSS雲存儲實作類
* @author: jeecg-boot
*/
@Service("ossFileService")
public class OssFileServiceImpl extends ServiceImpl<OssFileMapper, OssFile> implements IOssFileService {
@Override
public void upload(MultipartFile multipartFile) throws Exception {
String fileName = multipartFile.getOriginalFilename();
fileName = CommonUtils.getFileName(fileName);
OssFile ossFile = new OssFile();
ossFile.setFileName(fileName);
//String url = OssBootUtil.upload(multipartFile,"upload/test");
//改成華為雲的
String url = ObsBootUtil.upload(multipartFile,"upload/test");
//update-begin--Author:scott Date:20201227 for:JT-361【檔案預覽】阿裡雲原生域名可以檔案預覽,自己映射域名kkfileview提示檔案下載下傳失敗-------------------
// 傳回阿裡雲原生域名字首URL
//ossFile.setUrl(OssBootUtil.getOriginalUrl(url));
// 傳回華為雲原生域名字首URL
ossFile.setUrl(ObsBootUtil.getOriginalUrl(url));
//update-end--Author:scott Date:20201227 for:JT-361【檔案預覽】阿裡雲原生域名可以檔案預覽,自己映射域名kkfileview提示檔案下載下傳失敗-------------------
this.save(ossFile);
}
@Override
public boolean delete(OssFile ossFile) {
try {
this.removeById(ossFile.getId());
//OssBootUtil.deleteUrl(ossFile.getUrl());
ObsBootUtil.deleteUrl(ossFile.getUrl());
}
catch (Exception ex) {
log.error(ex.getMessage(),ex);
return false;
}
return true;
}
}
然後就大功告成了!!!