天天看點

jeecg-boot中上傳圖檔到華為雲obs雲存儲中

大家好,我是雄雄,歡迎關注微信公衆号:雄雄的小課堂。
jeecg-boot中上傳圖檔到華為雲obs雲存儲中

前言

jeecg-boot

架構中,其實對接的功能還是挺多的,其中就有檔案雲存儲伺服器,不過是阿裡雲

oss

的,那如果我們使用的是七牛雲,或者華為雲obs呢?我們需要改哪些内容才能實作上傳

obs

的目的呢,今天我們就來看看如何使用

jeecg-boot

來實作将檔案(圖檔)上傳到華為雲

obs

中。

配置nacos

因為我們用的是微服務版本,是以配置都在

nacos

中,如果是普通的

boot

版本的話,直接在

yml

檔案中寫配置就行。

nacos

的配置如下:

  1. 找到

    jeecg

    節點,修改

    uploadType

    的值:
uploadType: hwobs
           

記住這個hwobs的值,我們需要在代碼中聲明一下它,相當于一個變量,這個值必須和代碼中聲明的那個變量的值一樣,不然就找不到了。

  1. 添加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";
           
jeecg-boot中上傳圖檔到華為雲obs雲存儲中

修改原來檔案上傳的方法

首先找到類

CommonUtils

,的

uploadOnlineImage

方法,修改成如下:

jeecg-boot中上傳圖檔到華為雲obs雲存儲中
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

方法:

jeecg-boot中上傳圖檔到華為雲obs雲存儲中
/**
     * 統一全局上傳
     *
     * @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

方法(當然你新寫一個也行):

jeecg-boot中上傳圖檔到華為雲obs雲存儲中
/**
 * @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;
	}

}
           

然後就大功告成了!!!