整合華為雲OBS上傳工具類

大稳·杨發表於2024-10-19

專案啟動的要加上配置檔案的掃描路徑

import com.example.config.ObsProperties;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@MapperScan("com.example.dao")
@SpringBootApplication
@EnableConfigurationProperties({ObsProperties.class})
public class DemoApplication {

    public static void main(String[] args) {
        System.out.println("----------服務開始啟動----------");
        SpringApplication.run(VirtualNumberApplication.class, args);
        System.out.println("-----------服務啟動成功----------");
    }

}

ObsProperties

在專案啟動的時候初始化HuaWeiOBSUtil類

import com.example.utils.HuaWeiOBSUtil;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;

/**
 * @description: 華為雲OBS配置資訊
 */
@ConfigurationProperties(prefix = "obs")
public class ObsProperties {
    private String domainName;
    private String bucketName;
    private String accessKeyId;
    private String accessKeySecret;
    private String endPoint;
    private String privateFile;

    public String getDomainName() {
        return domainName;
    }

    public void setDomainName(String domainName) {
        this.domainName = domainName;
    }

    public String getBucketName() {
        return bucketName;
    }

    public void setBucketName(String bucketName) {
        this.bucketName = bucketName;
    }

    public String getAccessKeyId() {
        return accessKeyId;
    }

    public void setAccessKeyId(String accessKeyId) {
        this.accessKeyId = accessKeyId;
    }

    public String getAccessKeySecret() {
        return accessKeySecret;
    }

    public void setAccessKeySecret(String accessKeySecret) {
        this.accessKeySecret = accessKeySecret;
    }

    public String getEndPoint() {
        return endPoint;
    }

    public void setEndPoint(String endPoint) {
        this.endPoint = endPoint;
    }

    public String getPrivateFile() {
        return privateFile;
    }

    public void setPrivateFile(String privateFile) {
        this.privateFile = privateFile;
    }

    @Bean
    public HuaWeiOBSUtil huaWeiOBSUtil() {
        return new HuaWeiOBSUtil(bucketName, accessKeyId, accessKeySecret, endPoint, privateFile);
    }
}

HuaWeiOBSUtil

package com.example.utils;

import com.exampleenums.IntegerValueEnum;
import com.example.enums.StringEnum;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.*;
import io.micrometer.common.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @description: 華為雲OBS工具類
 */
public class HuaWeiOBSUtil {
    /*** 檔案外鏈過期時間,7天 */
    private static long expire = 7 * 24 * 60 * 60;
    /*** 檔案外鏈訪問埠 */
    private static String port = ":443";
    private static String bucketName;
    private static String ak;
    private static String sk;
    private static String endPoint;
    private static String privateFile;
    /*** OBS操作客戶端 */
    private static ObsClient obsClient = null;
    private static final String SEPARATOR = StringEnum.STRING_RIGHT_SLASH.getValue();
    private static Logger log = LoggerFactory.getLogger(HuaWeiOBSUtil.class);

    public HuaWeiOBSUtil(String bucketName, String ak, String sk, String endPoint, String privateFile) {
        HuaWeiOBSUtil.bucketName = bucketName;
        HuaWeiOBSUtil.ak = ak;
        HuaWeiOBSUtil.sk = sk;
        HuaWeiOBSUtil.endPoint = endPoint;
        HuaWeiOBSUtil.privateFile = privateFile;
        createObsClientInstance();
    }

    public static String getBucketName() {
        return bucketName;
    }

    public static String getAk() {
        return ak;
    }

    public static String getSk() {
        return sk;
    }

    public static String getEndPoint() {
        return endPoint;
    }

    /**
     * 獲取OBS操作客戶端
     */
    private static void createObsClientInstance() {
        synchronized (ObsClient.class) {
            try {
                if (obsClient == null) {
                    obsClient = new ObsClient(ak, sk, endPoint);
                }
                createBucket(bucketName, endPoint);
            } catch (Exception e) {
                log.error("連線華為雲端儲存伺服器異常:" + e.getMessage(), e);
            }
        }
    }

    /**
     * 建立儲存桶
     *
     * @param bucketName
     * @param endPoint
     */
    public static void createBucket(String bucketName, String endPoint) {
        try {
            if (!headBucket(bucketName)) {
                CreateBucketRequest request = new CreateBucketRequest();
                // 設定儲存桶名稱
                request.setBucketName(bucketName);
                // 設定桶區域位置,從endPoint中擷取,如果Location設定的區域與endPoint中的區域不是同一個,則建立會報錯
                request.setLocation(getRegion(endPoint));
                // 設定桶訪問許可權為公共讀,預設是私有讀寫
                request.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);
                // 建立桶成功
                ObsBucket bucket = obsClient.createBucket(request);
                log.info("建立桶成功,返回RequestId:{}", bucket.getRequestId());
            }
        } catch (ObsException e) {
            // 建立桶失敗
            log.error("HTTP Code: {}", e.getResponseCode());
            log.error("Error Code: {}", e.getErrorCode());
            log.error("Error Message: {}", e.getErrorMessage());
            log.error("Request ID: {}", e.getErrorRequestId());
            log.error("Host ID: {}", e.getErrorHostId());
        }

    }

    public AccessControlList getObjectAcl(String objectName) {
        AccessControlList objectAcl = obsClient.getObjectAcl(bucketName, objectName);
        return objectAcl;
    }

    /**
     * 獲取上傳檔案的基礎路徑
     *
     * @return
     */
    public static String getBasisUrl() {
        // 實示例:http協議 + 儲存桶名稱 + . + endPoint + port + /
        return getHttpProtocol(endPoint)
                + StringEnum.STRING_TWO_RIGHT_SLASH.getValue() + bucketName + StringEnum.STRING_POINT.getValue() + endPoint
                .replace(getHttpProtocol(endPoint) + StringEnum.STRING_TWO_RIGHT_SLASH.getValue(), StringEnum.STRING_EMPTY.getValue())
                + port + SEPARATOR;
    }

    /**
     * 獲取上傳檔案的基礎路徑
     *
     * @param bucketName
     * @return
     */
    public static String getBasisUrl(String bucketName) {
        // 實示例:http協議 + 儲存桶名稱 + . + endPoint + port + /
        return getHttpProtocol(endPoint)
                + StringEnum.STRING_TWO_RIGHT_SLASH.getValue() + bucketName + StringEnum.STRING_POINT.getValue() + endPoint
                .replace(getHttpProtocol(endPoint) + StringEnum.STRING_TWO_RIGHT_SLASH.getValue(), StringEnum.STRING_EMPTY.getValue())
                + port + SEPARATOR;
    }

    /**
     * 獲取區域
     *
     * @param endPoint
     * @return
     */
    public static String getRegion(String endPoint) {
        String substring = endPoint.substring(endPoint.indexOf(StringEnum.STRING_POINT.getValue()) + IntegerValueEnum.ONE.getValue());
        return substring.substring(IntegerValueEnum.ZERO.getValue(), substring.indexOf(StringEnum.STRING_POINT.getValue()));
    }

    /**
     * 獲取http協議
     *
     * @param endPoint
     * @return
     */
    public static String getHttpProtocol(String endPoint) {
        return endPoint.substring(IntegerValueEnum.ZERO.getValue(), endPoint.indexOf(StringEnum.STRING_COLON.getValue()));
    }

    /***
     * 刪除儲存桶** @param bucketName*
     *
     * @return
     */
    public static HeaderResponse deleteBucket(String bucketName) {
        return obsClient.deleteBucket(bucketName);
    }

    /***
     * 判斷儲存桶是否存在** @param bucketName*
     *
     * @return
     */
    public static boolean headBucket(String bucketName) {
        return obsClient.headBucket(bucketName);
    }

    /**
     * 上傳字元
     *
     * @param bucketName
     * @param objectName
     * @param content
     * @return
     */
    public static PutObjectResult putObjectByStr(String bucketName, String objectName, String content) {
        if (StringUtils.isBlank(content)) {
            return null;
        }
        // 重新構建objectName
        objectName = buildObjectName(objectName);
        return obsClient.putObject(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
    }

    /**
     * 上傳byte
     *
     * @param bucketName
     * @param objectName
     * @param content
     * @return
     */
    public static PutObjectResult putObjectByByte(String bucketName, String objectName, byte[] content, String fileName) {
        return putObjectByInput(bucketName, objectName, new ByteArrayInputStream(content), fileName);
    }

    /**
     * 上傳byte
     *
     * @param bucketName
     * @param objectName
     * @param content
     * @return
     */
    public static PutObjectResult putPrivateObjectByByte(String bucketName, String objectName, byte[] content, String fileName) {
        return putObjectByInput(bucketName, objectName, new ByteArrayInputStream(content), fileName);
    }

    /**
     * 上傳輸入流
     *
     * @param bucketName
     * @param objectName
     * @param inputStream
     * @return
     */
    public static PutObjectResult putObjectByInput(String bucketName, String objectName, InputStream inputStream,
                                                   String fileName) {
        String acl = "private";
        // 重新構建objectName
        objectName = buildObjectName(objectName);
        PutObjectRequest putObjectRequest = setObjectMetadata(bucketName, objectName, fileName, acl);
        putObjectRequest.setInput(inputStream);
        return obsClient.putObject(putObjectRequest);
    }

    /**
     * 上傳檔案輸入流
     *
     * @param bucketName
     * @param objectName
     * @param fileInputStream
     * @return
     */
    public static PutObjectResult putObjectByFileInput(String bucketName, String objectName,
                                                       FileInputStream fileInputStream) {
        // 重新構建objectName
        objectName = buildObjectName(objectName);
        return obsClient.putObject(bucketName, objectName, fileInputStream);
    }

    /**
     * 透過MultipartFile,上傳檔案
     *
     * @param bucketName
     * @param objectName
     * @param media
     * @return
     * @throws IOException
     */
    public static PutObjectResult putObjectByMultipartFile(String bucketName, String objectName, MultipartFile media)
            throws IOException {
        // 重新構建objectName
        objectName = buildObjectName(objectName);
        return obsClient.putObject(bucketName, objectName, media.getInputStream());
    }

    /**
     * 上傳本地檔案
     *
     * @param bucketName
     * @param objectName 上傳儲存的路徑
     * @param file
     * @return
     */
    public static PutObjectResult putObjectByFile(String bucketName, String objectName, File file, String acl) {
        // 重新構建objectName
        objectName = buildObjectName(objectName);
        PutObjectRequest putObjectRequest = setObjectMetadata(bucketName, objectName, file.getName(), acl);
        putObjectRequest.setFile(file);
        return obsClient.putObject(putObjectRequest);
    }

    /**
     * 下載檔案到本地
     *
     * @param bucketName
     * @param objectName
     * @param filePath
     * @return
     * @throws Exception
     */
    public static boolean downloadObject(String bucketName, String objectName, String filePath) throws Exception {
        if (StringUtils.isBlank(filePath)) {
            return false;
        }
        // 重新構建objectName
        objectName = buildObjectName(objectName);
        filePath = filePath.replace("\\", SEPARATOR);
        InputStream input = null;
        FileOutputStream fileOutputStream = null;
        try {
            // 獲取物件
            ObsObject obsObject = obsClient.getObject(bucketName, objectName);
            // 讀取物件內容
            input = obsObject.getObjectContent();
            if (input == null) {
                return false;
            }
            // 獲取資料夾路徑
            if (filePath.contains(SEPARATOR)) {
                String dir = filePath.substring(IntegerValueEnum.ZERO.getValue(), filePath.lastIndexOf(SEPARATOR));
                File difFile = new File(dir);
                if (!difFile.exists()) {
                    // 建立資料夾
                    boolean mkdirs = difFile.mkdirs();
                }
            }
            File file = new File(filePath);
            fileOutputStream = new FileOutputStream(file);
            byte[] b = new byte[1024];
            int len;
            while ((len = input.read(b)) != IntegerValueEnum.NEGATIVE_ONE.getValue()) {
                fileOutputStream.write(b, IntegerValueEnum.ZERO.getValue(), len);
            }
            return true;
        } finally {
            if (fileOutputStream != null) {
                fileOutputStream.close();
            }
            if (input != null) {
                input.close();
            }
        }
    }

    /**
     * 獲取檔案內容
     *
     * @param bucketName
     * @param objectName
     * @return
     * @throws IOException
     */
    public static String getObjectContent(String bucketName, String objectName) throws IOException {
        // 重新構建objectName
        objectName = buildObjectName(objectName);
        InputStream input = null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            ObsObject obsObject = obsClient.getObject(bucketName, objectName);
            // 讀取物件內容
            input = obsObject.getObjectContent();
            byte[] b = new byte[1024];
            int len;
            while ((len = input.read(b)) != IntegerValueEnum.NEGATIVE_ONE.getValue()) {
                bos.write(b, IntegerValueEnum.ZERO.getValue(), len);
            }
            return new String(bos.toByteArray());
        } finally {
            bos.close();
            if (input != null) {
                input.close();
            }
        }
    }

    /**
     * 獲取檔案輸入流
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public static InputStream getObject(String bucketName, String objectName) {
        // 重新構建objectName
        objectName = buildObjectName(objectName);
        return obsClient.getObject(bucketName, objectName).getObjectContent();
    }

    /**
     * 指定數目和字首列舉
     *
     * @param bucketName
     * @param prefix
     * @param maxKeys
     * @return
     */
    public static List<ObsObject> listObjects(String bucketName, String prefix, Integer maxKeys) {
        prefix = prefix.startsWith(StringEnum.STRING_RIGHT_SLASH.getValue()) ? prefix.substring(IntegerValueEnum.ONE.getValue()) : prefix;
        ListObjectsRequest request = new ListObjectsRequest(bucketName);
        // 設定列舉的物件個數
        request.setMaxKeys(maxKeys);
        // 設定列舉的物件需要帶有指定字首
        request.setPrefix(prefix);
        ObjectListing result = obsClient.listObjects(request);
        return result.getObjects();
    }

    /**
     * 列舉指定字首的全部物件
     *
     * @param bucketName
     * @param prefix
     * @return
     */
    public static List<ObsObject> listAllObjects(String bucketName, String prefix) {
        prefix = prefix.startsWith(StringEnum.STRING_RIGHT_SLASH.getValue()) ? prefix.substring(IntegerValueEnum.ONE.getValue()) : prefix;
        List<ObsObject> list = new ArrayList<>();
        ListObjectsRequest request = new ListObjectsRequest(bucketName);
        // 設定列舉的物件個數
        request.setMaxKeys(1000);
        // 設定列舉的物件需要帶有指定字首
        request.setPrefix(prefix);
        ObjectListing result;
        do {
            result = obsClient.listObjects(request);
            request.setMarker(result.getNextMarker());
            list.addAll(result.getObjects());
        } while (result.isTruncated());
        return list;
    }

    /**
     * 刪除單個物件
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public static DeleteObjectResult deleteObject(String bucketName, String objectName) {
        // 重新構建objectName
        objectName = buildObjectName(objectName);
        return obsClient.deleteObject(bucketName, objectName);
    }

    /**
     * 複製物件
     *
     * @param sourceBucketName
     * @param sourceObjectName
     * @param destBucketName
     * @param destObjectName
     * @return
     */
    public static CopyObjectResult copyObject(String sourceBucketName, String sourceObjectName, String destBucketName,
                                              String destObjectName) {
        return obsClient.copyObject(sourceBucketName, sourceObjectName, destBucketName, destObjectName);
    }

    /**
     * 複製物件
     *
     * @param sourceBucketName
     * @param sourceObjectName
     * @param destBucketName
     * @param destObjectName
     * @return
     */
    public static CopyObjectResult copyObject1(String sourceBucketName, String sourceObjectName, String destBucketName,
                                               String destObjectName) {
        // 重新構建objectName
        sourceObjectName = buildObjectName(sourceObjectName);
        destObjectName = buildObjectName(destObjectName);
        return obsClient.copyObject(sourceBucketName, sourceObjectName, destBucketName, destObjectName);
    }

    /**
     * 判斷物件是否存在
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public static boolean doesObjectExist(String bucketName, String objectName) {
        // 重新構建objectName
        objectName = buildObjectName(objectName);
        return obsClient.doesObjectExist(bucketName, objectName);
    }

    /**
     * 獲取檔案外鏈
     *
     * @param bucketName
     * @param objectName
     * @param expires    大於等於0的整型數,單位:秒
     * @return
     */
    public static String getSignedUrl(String bucketName, String objectName, Long expires) {
        // 重新構建objectName
        objectName = buildObjectName(objectName);
        TemporarySignatureRequest request = new TemporarySignatureRequest(HttpMethodEnum.GET, expires);
        request.setBucketName(bucketName);
        request.setObjectKey(objectName);
        TemporarySignatureResponse response = obsClient.createTemporarySignature(request);
        return response.getSignedUrl();
    }

    /**
     * 獲取檔案外鏈-url有效時間預設7天
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public static String getSignedUrl(String bucketName, String objectName) {
        return getSignedUrl(bucketName, objectName, expire);
    }

    /**
     * 重新構建objectName
     *
     * @param objectName
     * @return
     */
    private static String buildObjectName(String objectName) {
        if (StringUtils.isBlank(objectName)) {
            return objectName;
        }
        // 去除開頭的/
        objectName = objectName.startsWith(StringEnum.STRING_RIGHT_SLASH.getValue()) ? objectName.substring(IntegerValueEnum.ONE.getValue())
                : objectName;
        // 去除?後邊的引數
        objectName = objectName.contains(StringEnum.STRING_QUESTION.getValue())
                ? objectName.substring(IntegerValueEnum.ZERO.getValue(), objectName.indexOf(StringEnum.STRING_QUESTION.getValue())) : objectName;
        return objectName;
    }

    /**
     * 傳入檔案訪問外鏈,返回objectName
     *
     * @param url
     * @return
     */
    public static String getObjectNameByUrl(String url) {
        if (StringUtils.isBlank(url)) {
            return url;
        }
        if (url.contains(getBasisUrl())) {
            // 去除minio基礎路徑
            url = url.replace(getBasisUrl(), StringEnum.STRING_EMPTY.getValue());
            // 去除?後邊的引數
            url = url.contains(StringEnum.STRING_QUESTION.getValue())
                    ? url.substring(IntegerValueEnum.ZERO.getValue(), url.indexOf(StringEnum.STRING_QUESTION.getValue())) : url;
        }
        return url;
    }

    public static String getContentType(String fileName) {
        // 檔案的字尾名
        if (fileName.lastIndexOf(StringEnum.STRING_POINT.getValue()) < IntegerValueEnum.ZERO.getValue()) {
            // 預設返回型別
            return StringEnum.STRING_EMPTY.getValue();
        }
        String fileExtension = fileName.substring(fileName.lastIndexOf(StringEnum.STRING_POINT.getValue()));
        if (".bmp".equalsIgnoreCase(fileExtension)) {
            return "image/bmp";
        }
        if (".gif".equalsIgnoreCase(fileExtension)) {
            return "image/gif";
        }
        if (".jpeg".equalsIgnoreCase(fileExtension) || ".jpg".equalsIgnoreCase(fileExtension)
                || ".png".equalsIgnoreCase(fileExtension)) {
            return "image/jpeg";
        }
        if (".png".equalsIgnoreCase(fileExtension)) {
            return "image/png";
        }
        if (".html".equalsIgnoreCase(fileExtension)) {
            return "text/html";
        }
        if (".txt".equalsIgnoreCase(fileExtension)) {
            return "text/plain";
        }
        if (".vsd".equalsIgnoreCase(fileExtension)) {
            return "application/vnd.visio";
        }
        if (".ppt".equalsIgnoreCase(fileExtension) || "pptx".equalsIgnoreCase(fileExtension)) {
            return "application/vnd.ms-powerpoint";
        }
        if (".doc".equalsIgnoreCase(fileExtension) || "docx".equalsIgnoreCase(fileExtension)) {
            return "application/msword";
        }
        if (".xml".equalsIgnoreCase(fileExtension)) {
            return "text/xml";
        }
        // 預設返回型別
        return StringEnum.STRING_EMPTY.getValue();
    }

    /**
     * 獲取檔案路徑
     *
     * @param profiles
     * @param fileName
     * @return
     */
    public static String getFilePath(String profiles, String fileName) {
        String acl = "private";
        // 獲取檔案字尾
        String suffix = fileName.substring(fileName.lastIndexOf(StringEnum.STRING_POINT.getValue()));
        // 按時間生產一個目錄
        String date = DateUtils.dateToString(new Date(), "yyyyMMdd");
        StringBuffer buffer = new StringBuffer();
        if (StringUtils.isNotEmpty(acl) && AccessControlList.REST_CANNED_PRIVATE.equals(convertAcl(acl))) {
            buffer.append(privateFile);
        }
        buffer.append(profiles).append(StringEnum.STRING_RIGHT_SLASH.getValue()).append(date)
                .append(StringEnum.STRING_RIGHT_SLASH.getValue());
        buffer.append(UUID.randomUUID().toString().replace(StringEnum.STRING_MINUS.getValue(), StringEnum.STRING_EMPTY.getValue()))
                .append(suffix);
        return buffer.toString();
    }

    /**
     * 獲取檔案訪問地址
     *
     * @param acl
     * @param filePath
     * @return
     */
    public static String getFileUrl(String filePath, Long expires) {
        filePath = getSignedUrl(bucketName, filePath, expires);
        return filePath;
    }

    /**
     * 設定上傳物件屬性許可權
     *
     * @param fileName
     * @param acl
     * @return
     */
    public static PutObjectRequest setObjectMetadata(String bucketName, String objectName, String fileName,
                                                     String acl) {
        PutObjectRequest request = new PutObjectRequest();
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType(getContentType(fileName));
        request.setMetadata(metadata);
        // 設定檔案訪問許可權 這裡是私有
        if (StringUtils.isNotEmpty(acl) && AccessControlList.REST_CANNED_PRIVATE.equals(convertAcl(acl))) {
            request.setAcl(AccessControlList.REST_CANNED_PRIVATE);
        }
        request.setBucketName(bucketName);
        request.setObjectKey(objectName);
        return request;
    }

    /**
     * 轉換字串許可權
     *
     * @param acl
     * @return
     */
    public static AccessControlList convertAcl(String acl) {
        AccessControlList aclObj;
        switch (acl) {
            case "private":
                aclObj = AccessControlList.REST_CANNED_PRIVATE;
                break;
            case "read_write":
                aclObj = AccessControlList.REST_CANNED_PUBLIC_READ_WRITE;
                break;
            default:
                aclObj = AccessControlList.REST_CANNED_PUBLIC_READ;
        }
        return aclObj;
    }
}

相關文章