华润对象存储(OBS)工具类

发布于:2024-03-14 ⋅ 阅读:(54) ⋅ 点赞:(0)


一、备注

1、ObjectBasicInfo、ObjectDetailInfo、ResultBody这三个类可自行替换或者去掉


二、工具类

package com.xxx.util;

import com.amazonaws.HttpMethod;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import com.xxx.entity.huarun.ObjectBasicInfo;
import com.xxx.entity.huarun.ObjectDetailInfo;
import com.xxx.entity.huarun.ResultBody;
import com.hitachivantara.common.util.DatetimeFormat;
import com.hitachivantara.core.http.Protocol;
import com.hitachivantara.core.http.client.ClientConfiguration;
import com.hitachivantara.hcp.build.HCPClientBuilder;
import com.hitachivantara.hcp.build.HCPNamespaceClientBuilder;
import com.hitachivantara.hcp.common.auth.LocalCredentials;
import com.hitachivantara.hcp.standard.api.HCPNamespace;
import com.hitachivantara.hcp.standard.api.event.ListObjectHandler;
import com.hitachivantara.hcp.standard.define.NextAction;
import com.hitachivantara.hcp.standard.model.HCPObject;
import com.hitachivantara.hcp.standard.model.HCPObjectSummary;
import com.hitachivantara.hcp.standard.model.request.impl.CopyObjectRequest;
import com.hitachivantara.hcp.standard.model.request.impl.ListObjectRequest;
import com.obs.services.ObsClient;
import com.obs.services.model.HeaderResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.web.multipart.MultipartFile;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.*;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;

/**
 * 华润对象存储(OBS)-工具类
 *
 * @author hcs
 * @date 2023/6/20 17:03
 */
@Slf4j
public class HuaRunOBSUtil {

    /**
     * 文件外链过期时间,7天
     */
    private static long expire = 7 * 24 * 60 * 60;

    /**
     * 文件外链访问端口
     */
    private static String port = "";

    private static RedisUtil redisUtil = SpringUtil.getBean(RedisUtil.class);

    private static String bucketName;
    private static String ak;
    private static String sk;
    private static String endPoint;
    private static String targetDomainName;
    private static String replaceDomainName;

    /**
     * OBS操作客户端
     */
    private static HCPNamespace obsClient = null;
    /**
     * 上传、下载文件时使用以下对象
     *
     * 解决报错:Received fatal alert: protocol_version
     *
     * 华润对象存储的服务器支持TLSv1.2(使用tcpdump命令抓包看到的)
     */
    private static AmazonS3 S3APIClient;

    //private static AmazonS3 hs3Client;

    /**
     * OBS操作客户端Map,key=bucketName,value=客户端
     */
    private static Map<String, HCPNamespace> obsClientMap = new HashMap<>();

    private static final String SEPARATOR = "/";

    public HuaRunOBSUtil(String bucketName, String ak, String sk, String endPoint, String port) {
        HuaRunOBSUtil.bucketName = bucketName;
        HuaRunOBSUtil.ak = ak;
        HuaRunOBSUtil.sk = sk;
        HuaRunOBSUtil.endPoint = endPoint;
        if (StringUtils.isNotBlank(port)) {
            HuaRunOBSUtil.port = ":" + port;
        }
        createObsClientInstance();
        S3APIClient = getInstance(endPoint, ak, sk, "S3SignerType", getHttpProtocol(endPoint));
    }

    public static String getBucketName() {
        return bucketName;
    }

    public static String getAk() {
        return ak;
    }

    public static String getSk() {
        return sk;
    }

    public static String getEndPoint() {
        return endPoint;
    }

    public static synchronized AmazonS3 getInstance(String endpoint, String ak, String sk,
                                                    String signature, String protocol) {
        synchronized (AmazonS3.class) {
            if (null == S3APIClient) {
                S3APIClient = getHCPCSS3Client(endpoint, ak, sk, signature, protocol);
            }
        }

        return S3APIClient;
    }

    /**
     * 获取亚马逊S3客户端
     *
     * @param endpoint
     * @param ak
     * @param sk
     * @param signature     S3SignerType - 表示V2
     *                      AWSS3V4SignerType - 表示V4
     * @param protocol
     * @return
     */
    private static AmazonS3 getHCPCSS3Client(String endpoint, String ak, String sk, String signature, String protocol) {

        log.info("开始\t创建S3客户端");

        com.amazonaws.ClientConfiguration clientConfig = new com.amazonaws.ClientConfiguration();
        //使用HTTP或HTTPS协议
        if (protocol.toUpperCase().equals("HTTP")) {
            clientConfig.setProtocol(com.amazonaws.Protocol.HTTP);
        } else {
            clientConfig.setProtocol(com.amazonaws.Protocol.HTTPS);
            try {
                SSLContextBuilder builder = new SSLContextBuilder();
                builder.loadTrustMaterial(null, new TrustStrategy() {
                    public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                        return true;
                    }
                });

                SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                        builder.build(),
                        /**
                         * 仅指定TLSv1.2协议,解决报错:Received fatal alert: protocol_version
                         *
                         * 如果加上其他版本的协议,有可能会报错:Received fatal alert: protocol_version
                         *
                         * 例如指定为TLSv1.1,使用tcpdump命令抓包时如果发现TLSv1.2,则该次交互时失败的
                         */
                        new String[]{"TLSv1.2"},
                        // For Java 1.7 , 1.8
                        //new String[]{"SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"},
                        // For Java1.6-1.7
                        //new String[] { "TLSv1" },
                        new String[]{"TLS_RSA_WITH_AES_128_CBC_SHA"},

                        NoopHostnameVerifier.INSTANCE);

                clientConfig.getApacheHttpClientConfig().setSslSocketFactory(sslsf);
            } catch (Exception e) {
                log.error("创建S3客户端出现异常:" + e.getMessage(), e);
            }
        }

        //连接池的连接数
        clientConfig.setMaxConnections(50);
        //V2签名 或 V4签名
        //S3SignerType - 表示V2
        //AWSS3V4SignerType - 表示V4
        clientConfig.setSignerOverride(signature);

        AmazonS3 client = AmazonS3ClientBuilder.standard()
                .withClientConfiguration(clientConfig)
                /**
                 * 以下配置为false:外链格式:存储桶.endpoint/目录/文件名
                 * 以下配置为true:外链格式:endpoint/存储桶/目录/文件名
                 */
                //.withPathStyleAccessEnabled(true)
                .withEndpointConfiguration(new com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration(endpoint, null))
                .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(ak, sk)))
                .build();

        log.info("成功\t创建S3客户端");
        return client;
    }

    /**
     * 获取OBS操作客户端
     *
     * @return
     */
    private static void createObsClientInstance() {
        try {
            if (obsClient == null) {
                synchronized (ObsClient.class) {
                    if (obsClient == null) {
                        log.info("createObsClientInstance--->bucketName={},ak={},sk={},endPoint={}", bucketName, ak, sk, endPoint);
                        ClientConfiguration clientConfig = new ClientConfiguration();
                        String httpProtocol = getHttpProtocol(endPoint);
                        clientConfig.setProtocol(httpProtocol.equalsIgnoreCase(Protocol.HTTPS.toString()) ? Protocol.HTTPS : Protocol.HTTP);
                        HCPNamespaceClientBuilder builder = HCPClientBuilder.defaultHCPClient();
                        obsClient = builder.withClientConfiguration(clientConfig)
                                .withCredentials(new LocalCredentials(ak, sk))
                                // 去除http协议
                                .withEndpoint(endPoint.replace(getHttpProtocol(endPoint) + "://", ""))
                                .withNamespace(bucketName)
                                .bulid();
                        obsClientMap.put(bucketName, obsClient);
                    }
                }
            }
        } catch (Exception e) {
            log.error("连接华润对象存储服务器异常:" + e.getMessage(), e);
        }
    }

    /**
     * 获取上传文件的基础路径
     *
     * @return url
     */
    public static String getBasisUrl() {
        //实示例:http协议 + 存储桶名称 + . + endPoint + port + /
        String basisUrl = getHttpProtocol(endPoint) + "://" + bucketName + "." + endPoint.replace(getHttpProtocol(endPoint) + "://", "") + (StringUtils.isNotBlank(port) ? port + SEPARATOR : "");
        log.info("getBasisUrl--->" + basisUrl);
        basisUrl = replaceDomainName(basisUrl);
        return basisUrl;
    }

    /**
     * 获取上传文件的基础路径
     *
     * @param bucketName
     * @return
     */
    public static String getBasisUrl(String bucketName) {
        //实示例:http协议 + 存储桶名称 + . + endPoint + port + /
        String basisUrl = getHttpProtocol(endPoint) + "://" + bucketName + "." + endPoint.replace(getHttpProtocol(endPoint) + "://", "") + (StringUtils.isNotBlank(port) ? port + SEPARATOR : "");
        log.info("getBasisUrl2--->" + basisUrl);
        basisUrl = replaceDomainName(basisUrl);
        return basisUrl;
    }

    /**
     * 根据url地址获取存储桶名称
     *
     * @param url
     * @return
     */
    public static String getBucketNameByUrl(String url) {
        if (StringUtils.isNotBlank(url) && StringUtils.isNotBlank(getHttpProtocol(endPoint))
                && url.contains(endPoint.replace(getHttpProtocol(endPoint) + "://", ""))) {
            String str = url.replace(getHttpProtocol(endPoint) + "://", "");
            return str.substring(0, str.indexOf("."));
        } else {
            // 华润只会使用一个存储桶(访问外链替换了域名导致不支持多个存储桶),这里直接返回
            log.info("getBucketNameByUrl--->返回默认存储桶" + HuaRunOBSUtil.bucketName);
            return HuaRunOBSUtil.bucketName;
        }
    }

    /**
     * 获取区域
     *
     * @param endPoint
     * @return
     */
    public static String getRegion(String endPoint) {
        String substring = endPoint.substring(endPoint.indexOf(".") + 1);
        return substring.substring(0, substring.indexOf("."));
    }

    /**
     * 获取http协议
     *
     * @param endPoint
     * @return
     */
    public static String getHttpProtocol(String endPoint) {
        return endPoint.substring(0, endPoint.indexOf(":"));
    }

    /**
     * 创建存储桶(不确定以下方式是否有用)
     *
     * @param bucketName
     * @return
     */
    public static void createBucket(String bucketName, String endPoint) {
        try {
            log.info("createBucket.bucketName--->" + bucketName);
            log.info("createBucket.endPoint--->" + endPoint);
            if (!headBucket(bucketName)) {
                ClientConfiguration clientConfig = new ClientConfiguration();
                String httpProtocol = getHttpProtocol(endPoint);
                clientConfig.setProtocol(httpProtocol.equalsIgnoreCase(Protocol.HTTPS.toString()) ? Protocol.HTTPS : Protocol.HTTP);
                HCPNamespaceClientBuilder builder = HCPClientBuilder.defaultHCPClient();
                HCPNamespace obsClient = builder.withClientConfiguration(clientConfig)
                        .withCredentials(new LocalCredentials(ak, sk))
                        // 去除http协议
                        .withEndpoint(endPoint.replace(getHttpProtocol(endPoint) + "://", ""))
                        .withNamespace(bucketName)
                        .bulid();
                obsClientMap.put(bucketName, obsClient);
            }
        } catch (Exception e) {
            log.error("createBucket出现异常:" + e.getMessage(), e);
        }
    }

    /**
     * 创建存储桶
     *
     * @param bucketName
     * @return
     */
    public static void createBucket(String bucketName) {
        try {
            log.info("createBucket.bucketName--->" + bucketName);
            if (!headBucket(bucketName)) {
                S3APIClient.createBucket(bucketName);
            }
        } catch (Exception e) {
            log.error("createBucket出现异常:" + e.getMessage(), e);
        }
    }

    /**
     * 删除存储桶
     *
     * @param bucketName
     * @return
     */
    public static void deleteBucket(String bucketName) {
        S3APIClient.deleteBucket(bucketName);
    }

    /**
     * 判断存储桶是否存在
     *
     * @param bucketName
     * @return
     */
    public static boolean headBucket(String bucketName) {
        try {
            return obsClient.doesNamespacesExist(bucketName);
        } catch (Exception e) {
            log.error("headBucket出现异常:" + e.getMessage(), e);
        }
        return false;
    }

    /**
     * 上传字符
     *
     * @param bucketName
     * @param objectName
     * @param content
     * @return
     */
    public static ResultBody putObjectByStr(String bucketName, String objectName, String content) {
        log.info("putObjectByStr--->bucketName={},objectName={},content={}", bucketName, objectName, content);
        if (StringUtils.isBlank(content)) {
            return null;
        }

        //重新构建objectName
        objectName = buildObjectName(objectName);

        String errorMsg = "";
        for (int i = 0; i < 3; i++) {
            try {
                S3APIClient.putObject(bucketName, objectName, content);
                return ResultBody.success(new ObjectBasicInfo("putObjectByStr", objectName));
            } catch (Exception e) {
                log.error("putObjectByStr出现异常:" + e.getMessage(), e);
                errorMsg = e.getMessage();
            }

        }
        return ResultBody.failure(errorMsg);
    }
    
    /**
     * 上传输入流
     *
     * @param bucketName
     * @param objectName
     * @param inputStream
     * @return
     */
    public static ResultBody putObjectByInput(String bucketName, String objectName, InputStream inputStream) {
        log.info("putObjectByInput--->bucketName={},objectName={}", bucketName, objectName);

        //重新构建objectName
        objectName = buildObjectName(objectName);

        String errorMsg = "";
        ObjectMetadata metadata = new ObjectMetadata();
        for (int i = 0; i < 3; i++) {
            try {
                metadata.setContentLength(inputStream.available());
                S3APIClient.putObject(bucketName, objectName, inputStream, metadata);
                return ResultBody.success(new ObjectBasicInfo("inputStream", objectName));
            } catch (Exception e) {
                log.error("第" + (i + 1) + "次putObjectByInput出现异常:" + e.getMessage(), e);
                errorMsg = e.getMessage();
            }
        }
        return ResultBody.failure(errorMsg);
    }
    
    /**
     * 上传文件输入流
     *
     * @param bucketName
     * @param objectName
     * @param fileInputStream
     * @return
     */
    public static ResultBody putObjectByFileInput(String bucketName, String objectName, FileInputStream fileInputStream) {
        log.info("putObjectByFileInput--->bucketName={},objectName={}", bucketName, objectName);
        
        return putObjectByInput(bucketName, objectName, fileInputStream);
    }

    /**
     * 通过MultipartFile,上传文件
     *
     * @param bucketName
     * @param objectName
     * @param media
     * @return
     */
    public static ResultBody putObjectByMultipartFile(String bucketName, String objectName, MultipartFile media) throws IOException {
        log.info("putObjectByMultipartFile--->bucketName={},objectName={}", bucketName, objectName);

        return putObjectByInput(bucketName, objectName, media.getInputStream());
    }
    
    /**
     * 上传本地文件
     *
     * @param bucketName
     * @param objectName
     * @param file
     * @return
     */
    public static ResultBody putObjectByFile(String bucketName, String objectName, File file) {
        log.info("putObjectByFile--->bucketName={},objectName={}", bucketName, objectName);

        //重新构建objectName
        objectName = buildObjectName(objectName);

        String errorMsg = "";
        for (int i = 0; i < 3; i++) {
            try {
                S3APIClient.putObject(bucketName, objectName, file);
                return ResultBody.success(new ObjectBasicInfo(file.getName(), objectName));
            } catch (Exception e) {
                log.error("第" + (i + 1) + "次putObjectByFile出现异常:" + e.getMessage(), e);
                errorMsg = e.getMessage();
            }
        }
        return ResultBody.failure(errorMsg);
    }
    
    /**
     * 下载文件到本地
     *
     * @param bucketName
     * @param objectName
     * @param filePath
     * @return
     */
    public static boolean downloadObject(String bucketName, String objectName, String filePath) throws Exception {
        log.info("downloadObject--->bucketName={},objectName={},filePath={}", bucketName, objectName, filePath);

        if (StringUtils.isBlank(filePath)) {
            return false;
        }
        //重新构建objectName
        objectName = buildObjectName(objectName);

        filePath = filePath.replace("\\", SEPARATOR);

        InputStream input = null;
        FileOutputStream fileOutputStream = null;
        try {
            S3Object obsObject = null;
            for (int i = 0; i < 3; i++) {
                try {
                    // 获取对象
                    obsObject = S3APIClient.getObject(bucketName, objectName);
                    break;
                } catch (Exception e) {
                    log.error("第" + (i + 1) + "次downloadObject出现异常:" + e.getMessage(), e);
                }
            }
            // 读取对象内容
            input = obsObject.getObjectContent();

            if (input == null) {
                return false;
            }

            //获取文件夹路径
            if (filePath.contains(SEPARATOR)) {
                String dir = filePath.substring(0, 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)) != -1) {
                fileOutputStream.write(b, 0, len);
            }
            return true;
        } finally {
            if (fileOutputStream != null) {
                fileOutputStream.close();
            }
            if (input != null) {
                input.close();
            }
        }
    }
    
    /**
     * 获取文件内容
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public static String getObjectContent(String bucketName, String objectName) throws IOException {
        log.info("getObjectContent--->bucketName={},objectName={}", bucketName, objectName);

        //重新构建objectName
        objectName = buildObjectName(objectName);

        InputStream input = null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            for (int i = 0; i < 3; i++) {
                try {
                    // 读取对象内容
                    input = S3APIClient.getObject(bucketName, objectName).getObjectContent();
                    break;
                } catch (Exception e) {
                    log.error("第" + (i + 1) + "次getObjectContent出现异常:" + e.getMessage(), e);
                }
            }

            byte[] b = new byte[1024];
            int len;
            while ((len = input.read(b)) != -1) {
                bos.write(b, 0, len);
            }

            return new String(bos.toByteArray());
        } catch (Exception e) {
            log.error("getObjectContent出现异常:" + e.getMessage(), e);
        } finally {
            bos.close();
            if (input != null) {
                input.close();
            }
        }
        return null;
    }

    /**
     * 获取文件输入流
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public static InputStream getObject(String bucketName, String objectName) {
        log.info("getObject--->bucketName={},objectName={}", bucketName, objectName);

        //重新构建objectName
        objectName = buildObjectName(objectName);

        for (int i = 0; i < 3; i++) {
            try {
                S3Object object = S3APIClient.getObject(bucketName, objectName);
                return object.getObjectContent();
            } catch (Exception e) {
                log.error("第" + (i + 1) + "次getObject出现异常:" + e.getMessage(), e);
            }
        }

        return null;
    }

    /**
     * 列举指定目录的全部对象
     *
     * @param bucketName
     * @param directoryPath
     * @return
     */
    public static ResultBody listAllObjects(String bucketName, String directoryPath) {
        log.info("listAllObjects--->bucketName={},directoryPath={}", bucketName, directoryPath);

        List<ObjectDetailInfo> objList = new ArrayList<>();
        try {
            HCPNamespace obsClient = obsClientMap.get(bucketName);
            ListObjectRequest request = new ListObjectRequest(directoryPath)
                    .withRecursiveDirectory(true);
            obsClient.listObjects(request, new ListObjectHandler() {
                @Override
                public NextAction foundObject(HCPObjectSummary obj) {
                    ObjectDetailInfo objInfo = new ObjectDetailInfo(obj.getName(),
                            obj.getKey(),
                            obj.getSize(),
                            obj.getType(),
                            DatetimeFormat.ISO8601_DATE_FORMAT.format(new Date(obj.getChangeTime())),
                            obj.getContentHash());
                    objList.add(objInfo);
                    return null;
                }
            });
        } catch (Exception e) {
            log.error("listAllObjects出现异常:" + e.getMessage(), e);
            return ResultBody.failure(e.getMessage());
        }
        return ResultBody.success(objList);
    }

    /**
     * 删除单个对象
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public static ResultBody deleteObject(String bucketName, String objectName) {
        log.info("deleteObject--->bucketName={},objectName={}", bucketName, objectName);

        //重新构建objectName
        objectName = buildObjectName(objectName);

        try {
            HCPNamespace obsClient = obsClientMap.get(bucketName);
            obsClient.deleteObject(bucketName, objectName);
            return ResultBody.success();
        } catch (Exception e) {
            log.error("deleteObject出现异常:" + e.getMessage(), e);
            return ResultBody.failure(e.getMessage());
        }
    }

    /**
     * 复制对象
     *
     * @param sourceBucketName
     * @param sourceObjectName
     * @param destBucketName
     * @param destObjectName
     * @return
     */
    public static boolean copyObject(String sourceBucketName, String sourceObjectName,
                                     String destBucketName, String destObjectName) {
        log.info("deleteObject--->sourceBucketName={},sourceObjectName={},destBucketName={},destObjectName={}", bucketName, sourceObjectName, destBucketName, destObjectName);

        CopyObjectRequest copyObjectRequest = new CopyObjectRequest();
        copyObjectRequest.withSourceNamespace(sourceBucketName);
        copyObjectRequest.withSourceKey(sourceObjectName);
        copyObjectRequest.withTargetNamespace(destBucketName);
        copyObjectRequest.withTargetKey(destObjectName);
        try {
            obsClient.copyObject(copyObjectRequest);
            return true;
        } catch (Exception e) {
            log.error("copyObject出现异常:" + e.getMessage(), e);
        }
        return false;
    }

    /**
     * 判断对象是否存在
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public static boolean doesObjectExist(String bucketName, String objectName) {
        log.info("deleteObject--->bucketName={},objectName={}", bucketName, objectName);

        //重新构建objectName
        objectName = buildObjectName(objectName);

        try {
            HCPNamespace obsClient = obsClientMap.get(bucketName);
            return obsClient.doesObjectExist(objectName);
        } catch (Exception e) {
            log.error("doesObjectExist出现异常:" + e.getMessage(), e);
        }
        return false;
    }

    /**
     * 获取文件外链
     *
     * @param bucketName
     * @param objectName
     * @param expires    单位:秒(s)
     * @return
     */
    public static String getSignedUrl(String bucketName, String objectName, Long expires) {
        log.info("getSignedUrl--->bucketName={},objectName={},expires={}", bucketName, objectName, expires);

        //重新构建objectName
        objectName = buildObjectName(objectName);
        Date expiration = new Date(System.currentTimeMillis() + (expires * 1000));

        try {
            //String e = endPoint.replace(getHttpProtocol(endPoint) + "://", "");
            //AmazonS3 hs3Client = newS3Client(e, ak, sk);
            // 生成预签名时间
            URL url = S3APIClient.generatePresignedUrl(new GeneratePresignedUrlRequest(bucketName, objectName).withExpiration(expiration).withMethod(HttpMethod.GET));

            String s = url.toString();
            log.info("这个是api生成的url------------------------------------>" + s);
            // 由于api返回的是http,这里自行替换为endpoint使用的协议
            s = s.replace(getHttpProtocol(s) + "://", getHttpProtocol(endPoint) + "://");
            log.info("替换协议后url------>" + s);
            s = replaceDomainName(s);
            return s;
        } catch (Exception e) {
            log.error("getSignedUrl出现异常:" + e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取文件外链-url有效时间默认7天
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public static String getSignedUrl(String bucketName, String objectName) {
        return getSignedUrl(bucketName, objectName, expire);
    }

    /**
     * 重新构建objectName
     *
     * @param objectName
     */
    private static String buildObjectName(String objectName) {
        if (StringUtils.isBlank(objectName)) {
            return objectName;
        }
        //去除开头的/
        objectName = objectName.startsWith("/") ? objectName.substring(1) : objectName;
        //去除?后边的参数
        objectName = objectName.contains("?") ? objectName.substring(0, objectName.indexOf("?")) : objectName;

        return objectName;
    }

    /**
     * 传入文件访问外链,返回objectName
     *
     * @param url
     * @return
     */
    public static String getObjectNameByUrl(String url) {
        if (StringUtils.isBlank(url)) {
            return url;
        }

        try {
            url = URLDecoder.decode(url, "UTF-8");
        } catch (Exception e) {
            log.error("getObjectNameByUrl获取文件外链失败:" + e.getMessage(), e);
        }

        if (url.contains(getBasisUrl())) {
            // 去除基础路径
            url = url.replace(getBasisUrl(), "");
            // 去除?后边的参数
            url = url.contains("?") ? url.substring(0, url.indexOf("?")) : url;
        }

        return url;
    }

    /**
     * 获取华润OBS文件外链
     *
     * @param redisKey
     * @param objectName
     * @return
     * @throws Exception
     */
    public static String getOBSFileUrl(String redisKey, String objectName) throws Exception {
        if (StringUtils.isBlank(objectName) || StringUtils.isBlank(redisKey) || OBSUtil.httpRegex(objectName)) {
            return "";
        }

        objectName = URLDecoder.decode(objectName, "UTF-8");

        //重新构建objectName
        objectName = buildObjectName(objectName);

        Object o = redisUtil.get(redisKey);
        String url = o == null ? null : o.toString();
        if (StringUtils.isNotBlank(url)) {
            return url;
        } else {
            //重新获取url
            String signedUrl = getSignedUrl(getBucketName(), objectName, expire);
            //保存访问url,有效期为6天
            redisUtil.set(redisKey, signedUrl, 6 * 24 * 60 * 60);

            return signedUrl;
        }
    }

    /**
     * 从指定存储桶获取华润OBS文件外链
     *
     * @param redisKey
     * @param objectName
     * @param bucketName
     * @return
     * @throws Exception
     */
    public static String getOBSFileUrl(String redisKey, String objectName, String bucketName) throws Exception {
        if (StringUtils.isBlank(objectName) || StringUtils.isBlank(redisKey) || StringUtils.isBlank(bucketName)) {
            return "";
        }

        //重新构建objectName
        objectName = buildObjectName(objectName);

        Object o = redisUtil.get(redisKey);
        String url = o == null ? null : o.toString();
        if (StringUtils.isNotBlank(url)) {
            return url;
        } else {
            //重新获取url
            String signedUrl = getSignedUrl(bucketName, objectName, expire);
            //保存访问url,有效期为6天
            redisUtil.set(redisKey, signedUrl, 6 * 24 * 60 * 60);

            return signedUrl;
        }
    }

    /**
     * 保存华润OBS文件外链至redis
     *
     * @param redisKey
     * @param url
     * @return
     */
    public static boolean setOBSFileUrl(String redisKey, String url) {
        Object o = redisUtil.get(redisKey);
        if (o != null) {
            String value = o.toString();
            //只保存新的外链,解决url重复保存导致redis保存的是过期外链的问题
            if (!value.equals(url)) {
                //保存访问url,有效期为6天
                return redisUtil.set(redisKey, url, 6 * 24 * 60 * 60);
            }
        } else {
            //保存访问url,有效期为6天
            return redisUtil.set(redisKey, url, 6 * 24 * 60 * 60);
        }
        return true;
    }

    /**
     * 删除华润OBS文件外链
     *
     * @param redisKey
     */
    public static void delOBSFileUrl(String redisKey) {
        //删除访问url
        redisUtil.del(redisKey);
    }

    /**
     * 替换域名
     *
     * @param url
     * @return
     */
    private static String replaceDomainName(String url){
        if (StringUtils.isNotBlank(replaceDomainName) && StringUtils.isNotBlank(targetDomainName)) {
            url = url.replace(targetDomainName, replaceDomainName);
            log.info("替换域名后url------>" + url);
        }
        return url;
    }

    public static void setTargetDomainName(String targetDomainName) {
        HuaRunOBSUtil.targetDomainName = targetDomainName;
    }

    public static void setReplaceDomainName(String replaceDomainName) {
        HuaRunOBSUtil.replaceDomainName = replaceDomainName;
    }
}

三、对象存储放在内网,如何实现外网访问

如果对象存储是放在内网的,可以按照以下示例配置ngin代理

nginx配置请参考:https://app.rwork.crc.com.cn/docs/dock9zVHp5WcpLYNKfjo5ACbU8g

结合代码中的targetDomainNamereplaceDomainName可实现外网访问

本文含有隐藏内容,请 开通VIP 后查看