美文网首页javaWeb学习springboot
SpringBoot2.x整合(cos,oss,本地挂载盘)文件

SpringBoot2.x整合(cos,oss,本地挂载盘)文件

作者: 小胖学编程 | 来源:发表于2021-02-08 11:38 被阅读0次

    由于项目升级,文件存储由本地磁盘(挂载盘)升级为cos(腾讯云)存储,由此实现了一套整合各家文件存储的项目。

    1. 设计思想

    1.1 使用到的设计模式

    1. 例如cos和oss提供的client不同,以及本地磁盘存储需要自己实现client端。所以需要自己实现一个公共的接口,使用适配器模式,将各种client端转换为统一的client接口实现;
    2. 业务端依旧使用Template类操作文件,Template类使用模板方法模式,来支持业务放进行扩展。
    3. Template类通过组合的方式选择client类,使用策略模式来自由的切换存储介质(cos,oss,本地磁盘)。

    1.2 设计思想

    项目默认提供cos腾讯云存储和本地挂载盘存储的template类。当业务方在依赖中移除腾讯cos的依赖,且使用阿里云oss的依赖后。template类将自动切换为阿里云oss的存储。

            <dependency>
                <groupId>com.tellme</groupId>
                <artifactId>xos-starter</artifactId>
                <version>0.0.1-SNAPSHOT</version>
                <exclusions>
                    <exclusion>
                        <artifactId>cos_api</artifactId>
                        <groupId>com.qcloud</groupId>
                    </exclusion>
                    <exclusion>
                        <groupId>com.tencent.cloud</groupId>
                        <artifactId>cos-sts-java</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    
            <dependency>
                <groupId>com.aliyun.oss</groupId>
                <artifactId>aliyun-sdk-oss</artifactId>
                <version>2.8.3</version>
            </dependency>
    

    其思想借鉴与SpringBoot2.x-Redis实现Jedis客户端和Lettuce客户端的切换。

    2. 代码实现

    2.1 pom依赖

    pom依赖中,使用SpringBoot2.0.4版本。

    引入了

    1. 腾讯云cos提供的jar;
    2. 阿里云oss提供的jar;
    3. 以及相关的工具jar;

    当然阿里云oss的依赖不向下传递。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.tellme</groupId>
        <artifactId>xos-starter</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.4.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-autoconfigure</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <optional>true</optional>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.retry</groupId>
                <artifactId>spring-retry</artifactId>
            </dependency>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <scope>provided</scope>
            </dependency>
    
            <!-- 通信-->
            <dependency>
                <groupId>com.squareup.okhttp3</groupId>
                <artifactId>okhttp</artifactId>
                <version>3.8.1</version>
            </dependency>
    
    
            <dependency>
                <groupId>com.qcloud</groupId>
                <artifactId>cos_api</artifactId>
                <version>5.6.8</version>
            </dependency>
            <dependency>
                <groupId>com.tencent.cloud</groupId>
                <artifactId>cos-sts-java</artifactId>
                <version>3.0.5</version>
            </dependency>
            <!--jar不向下传递(阿里云oos)-->
            <dependency>
                <groupId>com.aliyun.oss</groupId>
                <artifactId>aliyun-sdk-oss</artifactId>
                <version>2.8.3</version>
                <scope>provided</scope>
            </dependency>
    
    
        </dependencies>
    
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-source-plugin</artifactId>
                    <version>3.0.1</version>
                    <executions>
                        <execution>
                            <id>attach-sources</id>
                            <goals>
                                <goal>jar</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    2.2 starter的实现

    在spring.factories文件中定义自动装配的类。

    image.png
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.tellme.os.config.OSAutoConfiguration
    

    2.3 client端(适配器模式)

    首先是需要提供一个项目内公共的接口类(OSClient)。无论各个厂商的client客户端都要进行适配。

    public interface OSClient {
    
        /**
         * 上传文件
         *
         * @param storageName  (bucketName)存储桶
         * @param relativePath 文件上传的地址
         * @param fileBytes    文件流
         */
        void uploadFile(String storageName, String relativePath, byte[] fileBytes);
    
        /**
         * 下载文件
         *
         * @param filePath 文件地址
         * @return 文件输出流
         */
        ByteArrayOutputStream downloadFile(String filePath);
    
        /**
         * 客户端关闭
         */
        void shutdown();
    }
    

    由于云文件存储,下载文件的方法是相同的,故可以使用模板方法模式来进行扩展。

    @Slf4j
    public abstract class NetOsClient implements OSClient {
    
        @Override
        public ByteArrayOutputStream downloadFile(String filePath) {
            ByteArrayOutputStream data;
            data = OkHttpUtil.get(filePath);
            if (data == null) {
                throw new OsException("下载照片失败,照片地址:" + filePath);
            }
            //转换流信息
            return data;
        }
    
    }
    

    2.3.1 适配腾讯云cos客户端

    @Data
    public class CosClient extends NetOsClient {
    
        private COSClient cosClient;
    
        /**
         *
         * @param bucketName   存储桶
         * @param relativePath 文件上传的地址
         * @param fileBytes    文件流
         */
        @Override
        public void uploadFile(String bucketName, String relativePath, byte[] fileBytes) {
            ByteArrayInputStream input = new ByteArrayInputStream(fileBytes);
            ObjectMetadata objectMetadata = new ObjectMetadata();
            // 设置输入流长度
            objectMetadata.setContentLength(input.available());
            cosClient.putObject(bucketName, relativePath, input, objectMetadata);
        }
        /**
         * 关闭客户端
         */
        @Override
        public void shutdown() {
            cosClient.shutdown();
        }
    }
    

    2.3.2 适配阿里云oss客户端

    @Data
    public class OssClient extends NetOsClient{
    
        private OSSClient ossClient;
    
        @Override
        public void uploadFile(String bucketName, String relativePath, byte[] fileBytes) {
            ByteArrayInputStream input = new ByteArrayInputStream(fileBytes);
            ObjectMetadata objectMetadata = new ObjectMetadata();
            // 设置输入流长度
            objectMetadata.setContentLength(input.available());
            ossClient.putObject(bucketName, relativePath, input, objectMetadata);
        }
    
        @Override
        public void shutdown() {
            ossClient.shutdown();
        }
    }
    

    2.3.3 适配本地挂载盘客户端

    @Slf4j
    public class FileOsClient implements OSClient {
    
        /**
         * @param bucketName  上传的根路径
         * @param relativePath 文件上传的地址
         * @param fileBytes    文件流
         */
        @Override
        public void uploadFile(String bucketName, String relativePath, byte[] fileBytes) {
            File file = new File(bucketName + File.separator + relativePath);
            //获取文件夹目录
            String fullPath = file.getParent();
            File dir = new File(fullPath);
            //创建目录
            dir.mkdirs();
            try {
                //构建输出流
                ByteArrayInputStream is = new ByteArrayInputStream(fileBytes);
                FileOutputStream os = new FileOutputStream(file);
                byte[] b = new byte[1024];
                int nRead;
                while ((nRead = is.read(b)) != -1) {
                    os.write(b, 0, nRead);
                }
            } catch (Exception e) {
                log.error("", e);
                throw new OsException("", e);
            }
        }
    
        /**
         * 读取本地文件
         *
         * @param filePath 文件地址
         * @return 文件数组输出流
         */
        @Override
        public ByteArrayOutputStream downloadFile(String filePath) {
            File file = new File(filePath);
            if (!file.exists()) {
                throw new OsException("文件不存在!");
            }
            InputStream is = IOUtil.getInputStream(file);
            return IOUtil.convertInputStream(is);
        }
    
        @Override
        public void shutdown() {
    
        }
    
    }
    

    2.4 template类(模板模式+策略模式)

    1. template通过组合的方式引入client对象,在Spring容器初始化的时候选择合适的client策略。
    2. template采用模板方法模式,可自由扩展。
    public interface OsTemplate {
    
        /**
         * 上传文件
         *
         * @param relativePath 上传文件的相对地址
         * @param fileBytes    文件流
         * @return 上传后的地址
         */
        String saveFile(String relativePath, byte[] fileBytes);
    
        /**
         * 拼接路径,上传照片
         *
         * @param modulePath 项目路径
         * @param fileSuffix 文件后缀
         * @param base64Str  base64
         * @return 格式:{@code PATH_COMMON / modulePath / calculatePath() /UUID.randomUUID() + fileSuffixEnum.getType()}
         */
        String saveFile(String modulePath, String fileSuffix, String base64Str);
    
        /**
         * 拼接路径,上传文件
         *
         * @param modulePath 项目路径
         * @param fileBytes  文件流
         * @param fileSuffix 文件后缀
         * @return 格式:{@code PATH_COMMON / modulePath / calculatePath() /UUID.randomUUID() + fileSuffixEnum.getType()}
         */
        String saveFile(String modulePath, byte[] fileBytes, String fileSuffix);
    
    
        /**
         * 拼接路径,上传到特定的存储桶
         *
         * @param bucketName 存储桶的名字
         * @param modulePath 项目路径
         * @param fileSuffix 文件后缀
         * @param fileBytes  文件流
         * @return 格式:{@code PATH_COMMON / modulePath / calculatePath() /UUID.randomUUID() + fileSuffix}
         */
        String saveFile(String bucketName, String modulePath, String fileSuffix, byte[] fileBytes);
    
        /**
         * 拼接路径,上传到特定的存储桶
         *
         * @param bucketName   存储桶的名字
         * @param relativePath 文件的相对路径
         * @param fileBytes    文件流
         * @return 格式:{@code PATH_COMMON / modulePath / calculatePath() /UUID.randomUUID() + fileSuffix}
         */
        String saveFile(String bucketName, String relativePath, byte[] fileBytes);
    
    
        /**
         * 文件下载
         *
         * @param filePath 文件地址
         * @return 下载字节流
         */
        ByteArrayOutputStream downloadFile(String filePath);
    
        /**
         * CDN前缀地址
         *
         * @return CDN地址
         */
        String getCdnHost();
    }
    

    2.4.1 云存储的template

    @Data
    @Slf4j
    public class NetOsTemplate implements OsTemplate {
    
        //cos连接对象
        protected OSClient client;
    
        protected OsConfigProperties osConfigProperties;
    
        /**
         * 存储介质:
         * cos存储的是:bucketName
         * file存储的是:根路径
         */
        protected String bucketName;
    
        /**
         * cdn地址
         */
        protected String cdnHost;
    
        protected static  String PATH_COMMON = "/xos";
    
    
        /**
         * (经常使用)使用配置文件的存储桶上传照片
         *
         * @param modulePath 模块路径
         * @param fileSuffix 文件后缀,需要携带.
         * @param base64Str  照片的base64信息
         * @return 图片上传的地址
         */
        public String saveFile(String modulePath, String fileSuffix, String base64Str) {
            return saveFile(bucketName, modulePath, fileSuffix, IOUtil.base64ToBytes(base64Str));
        }
    
    
        /**
         * (经常使用)使用配置文件的存储桶上传文件
         *
         * @param modulePath 模块路径
         * @param fileSuffix 文件后缀,需要携带.
         * @param fileBytes  文件流字节数组
         * @return 图片上传的地址
         */
        public String saveFile(String modulePath, byte[] fileBytes, String fileSuffix) {
            return saveFile(bucketName, modulePath, fileSuffix, fileBytes);
        }
    
        /**
         * 腾讯云上传文件
         * 只需要传入模块目录,自动拼装上传腾讯云的路径。
         * {@code PATH_COMMON / modulePath / calculatePath() /UUID.randomUUID() + fileSuffixEnum.getType()}
         *
         * @param bucketName 存储目录
         * @param modulePath  模块路径(业务路径格式:{@code exercise/plan/answerImage })
         * @param fileSuffix  文件后缀,需要携带.
         * @param fileBytes   文件流字节数组
         * @return 图片上传的地址
         */
        public String saveFile(String bucketName, String modulePath, String fileSuffix, byte[] fileBytes) {
            return saveFile(bucketName, getRelativeDir(modulePath) + getFileName(fileSuffix), fileBytes);
        }
    
        /**
         * 腾讯云上传文件
         * 返回的路径:{@code PATH_COMMON / modulePath / calculatePath() /UUID.randomUUID() + fileSuffix}
         *
         * @param relativePath 上传文件的相对地址
         * @param fileBytes    文件流
         * @return 保存到腾讯云的地址
         */
        @Override
        public String saveFile(String relativePath, byte[] fileBytes) {
            //读取配置信息的存储桶信息
            return saveFile(bucketName, relativePath, fileBytes);
        }
    
        /**
         * 腾讯云上传文件
         *
         * @param bucketName  存储桶
         * @param relativePath 文件的相对地址
         * @param fileBytes    文件流的字节数组
         * @return 腾讯云上的相对地址
         */
        public String saveFile(String bucketName, String relativePath, byte[] fileBytes) {
            client.uploadFile(bucketName, relativePath, fileBytes);
            return relativePath;
        }
    
    
        /**
         * 文件下载
         * 若下载失败或者照片不存在,抛出{@link com.xdf.pscommon.os.exception.OsException}异常。
         *
         * @param filePath 文件地址
         * @return 文件输出流
         */
        @Override
        public ByteArrayOutputStream downloadFile(String filePath) {
            return client.downloadFile(filePath);
        }
    
    
        /**
         * 获取腾讯云的前缀地址
         *
         * @return 腾讯云的CDN地址
         */
        public String getCdnHost() {
            return cdnHost;
        }
    
        /**
         * 创建文件夹的相对路径
         *
         * @return 格式:{@code exam/modulePath/2021/11/1}
         */
        protected String getRelativeDir(String modulePath) {
            return PATH_COMMON + File.separator + modulePath + File.separator + calculatePath();
        }
    
        /**
         * 创建文件名(使用UUID创建)
         */
        protected String getFileName(String fileSuffix) {
            return UUID.randomUUID() + fileSuffix;
        }
    
        /**
         * 时间戳作为路径名
         */
        protected String calculatePath() {
            Calendar calendar = Calendar.getInstance();
            String year = String.valueOf(calendar.get(Calendar.YEAR));
            String month = String.valueOf(calendar.get(Calendar.MONTH) + 1);
            String date = String.valueOf(calendar.get(Calendar.DATE));
            return year + "/" + month + "/" + date + "/";
        }
    
    }
    

    2.4.2 挂载盘存储的template

    挂载盘在创建目录时,需要随机路由到不同的挂载盘上,所以需要重写getRelativeDir方法即可。

    public class FileOsTemplate extends NetOsTemplate {
    
        private long index;
    
        private final static String ROOTPATH = "rootPath";
        private final static String FORWARDMARK = "forwardMark";
    
    
        /**
         * 路径填充挂载盘路径
         */
        @Override
        public String getRelativeDir(String modulePath) {
            OperatingSystemEnum operatingSystem = IOUtil.getOperatingSystem();
            if (OperatingSystemEnum.LINUX.equals(operatingSystem) &&
                    osConfigProperties.getFile().getRootPath() != null &&
                    osConfigProperties.getFile().getRootPath().size() > 1) {
                Map<String, String> rootPathMap = returnRootPathMap(osConfigProperties.getFile().getRootPath());
                return PATH_COMMON + File.separator + rootPathMap.get(FORWARDMARK) + File.separator + modulePath + File.separator + calculatePath();
            } else {
                return super.getRelativeDir(modulePath);
            }
        }
    
        /**
         * 返回挂载盘的具体配置
         */
        private Map<String, String> returnRootPathMap(Map<String, String> rootPaths) {
            int size = 2; //最少有个原磁盘以及加的共享盘,共享磁盘个数
            if (rootPaths != null && rootPaths.size() > 1) {
                size = rootPaths.size() - 1;
            }
            int rootPathIndex = Math.toIntExact(index++ % size);
            Map<String, String> rootPathMap = new HashMap<>();
            switch (rootPathIndex) {
                case 0:
                    rootPathMap.put(ROOTPATH, rootPaths.get("files1"));
                    rootPathMap.put(FORWARDMARK, "files1/");
                    break;
                case 1:
                    rootPathMap.put(ROOTPATH, rootPaths.get("files2"));
                    rootPathMap.put(FORWARDMARK, "files2/");
                    break;
                case 2:
                    rootPathMap.put(ROOTPATH, rootPaths.get("files3"));
                    rootPathMap.put(FORWARDMARK, "files3/");
                    break;
                default:
                    rootPathMap.put(ROOTPATH, rootPaths.get("files"));
                    rootPathMap.put(FORWARDMARK, "files/");
                    break;
            }
            return rootPathMap;
        }
    
    }
    

    2.5 加入到Spring容器中

    1. 使用@ConditionalOnClass注解,当某个依赖存在时,才加载bean类;
    2. 使用@ConditionalOnProperty注解,当某个配置存在时,才加载bean类;
    3. 使用@Import注解,当多个配置均存在时,优先加载哪个配置;
    4. 配合@ConditionalOnMissingBean(name = "netOsTemplate")注解,当加载某个配置后,便不加载同名的bean。

    2.5.1 配置类

    当本地磁盘加载时,支持windows,mac,linux各个配置。

    @Data
    @ConfigurationProperties("xos")
    public class OsConfigProperties {
    
        /**
         * 腾讯云COS配置
         */
        private CosProperties cos;
    
        /**
         * 阿里云OOS配置
         */
        private OssProperties oss;
        /**
         * 共享盘文件存储配置
         */
        private FileProperties file;
    
        /**
         * 云存储——存储桶
         */
        private String bucketName;
        /**
         * 云存储——cdn地址
         */
        private String cdnHost;
    
        @Data
        public static class CosProperties {
    
            private String accessKeyId;
    
            private String accessKeySecret;
    
            private String region;
    
    
        }
    
    
        @Data
        public static class OssProperties {
            private String endpoint;
    
            private String accessKeyId;
    
            private String accessKeySecret;
    
        }
    
    
        @Data
        public static class FileProperties {
            /**
             * Linux支持的根路径
             */
            private String linuxRootPath;
            /**
             * window支持的根路径
             */
            private String windowsRootPath;
            /**
             * mac支持的根路径
             */
            private String macRootPath;
    
            /**
             * Linux系统设置,挂载盘映射关系
             */
            private Map<String, String> rootPath;
            /**
             * cdn地址
             */
            private String cdnHost;
        }
    }
    

    2.5.2 腾讯云cos的client加入到Spring中

    只有存在COSClient.class类且存在xos.cos.accessKeyId配置时,才会加载改bean。

    @Configuration
    @ConditionalOnClass(COSClient.class)
    public class CosClientConfiguration {
    
        /**
         * 初始化腾讯云客户端
         */
        @Bean(name = "netOSClient", destroyMethod = "shutdown")
        @ConditionalOnProperty("xos.cos.accessKeyId")
        @ConditionalOnMissingBean(name = "netOSClient")
        public OSClient cosClient(OsConfigProperties osConfigProperties) {
            CosClient cosClient = new CosClient();
            OsConfigProperties.CosProperties cosProperties = osConfigProperties.getCos();
            // 1 初始化用户身份信息(secretId, secretKey)。
            COSCredentials cred = new BasicCOSCredentials(cosProperties.getAccessKeyId(), cosProperties.getAccessKeySecret());
            // 2 设置 bucket 的区域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
            // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
            Region cosRegion = new Region(cosProperties.getRegion());
            ClientConfig clientConfig = new ClientConfig(cosRegion);
            // 3 生成 cos 客户端。
            COSClient cosClient = new COSClient(cred, clientConfig);
            cosClient.setCosClient(cosClient);
            return cosClient;
        }
    
    }
    

    2.5.3 阿里云oss的client加入到Spring容器

    @Configuration
    @ConditionalOnClass(OSSClient.class)
    public class OssClientConfiguration {
    
        /**
         * 初始化阿里云oss客户端
         */
        @Bean(name = "netOSClient", destroyMethod = "shutdown")
        @ConditionalOnProperty("xos.oss.accessKeyId")
        @ConditionalOnMissingBean(name = "netOSClient")
        public  OSClient ossClient(OsConfigProperties osConfigProperties) {
            OssClient ossClient = new OssClient();
            OsConfigProperties.OssProperties ossProperties = osConfigProperties.getOss();
            OSSClient ossClient = new OSSClient(ossProperties.getEndpoint(), ossProperties.getAccessKeyId(), ossProperties.getAccessKeySecret());
            ossClient.setOssClient(ossClient);
            return ossClient;
        }
    }
    

    2.5.4 自动装配的config

    1. @EnableConfigurationProperties将配置文件类加入到Spring容器;
    2. @Import({CosClientConfiguration.class,OssClientConfiguration.class})将config类加入到Spring容器;
    @Slf4j
    @Configuration
    @EnableConfigurationProperties(value = OsConfigProperties.class)
    @Import({CosClientConfiguration.class,OssClientConfiguration.class})
    public class OSAutoConfiguration {
    
    
    
        /**
         * 初始化文件流客户端
         */
        @Bean
        @ConditionalOnMissingBean(name = "fileClient")
        public lFileOsClient fileClient(OsConfigProperties osConfigProperties) {
            return new FileOsClient();
        }
    
    
        /**
         * 创建云存储的模板类
         *
         * @param oSClient           cos的客户端
         * @param osConfigProperties 配置信息
         * @return 模板工具类
         */
        @Bean
        @Primary
        @ConditionalOnBean(name = {"netOSClient"})
        @ConditionalOnMissingBean(name = "netOsTemplate")
        public NetOsTemplate netOsTemplate(@Qualifier("netOSClient") OSClient oSClient, OsConfigProperties osConfigProperties) {
            NetOsTemplate osTemplate = new NetOsTemplate();
            //放入客户端
            osTemplate.setClient(oSClient);
            osTemplate.setBucketName(osConfigProperties.getBucketName());
            //配置文件
            osTemplate.setOsConfigProperties(osConfigProperties);
            osTemplate.setCdnHost(osConfigProperties.getCdnHost());
            return osTemplate;
        }
    
        /**
         * 共享盘OS的模板类
         */
        @Bean
        @ConditionalOnMissingBean(name = "fileOsTemplate")
        public OsTemplate fileOsTemplate(FileOsClient cosClient, OsConfigProperties osConfigProperties) {
            FileOsTemplate osTemplate = new FileOsTemplate();
            //放入客户端
            osTemplate.setClient(cosClient);
            OperatingSystemEnum operatingSystem = IOUtil.getOperatingSystem();
            osConfigProperties.FileProperties fileProperties =osConfigProperties.getFile();
            //获取对应的根路径
            String bucketName = null;
            String cdnHost = null;
            if (fileProperties != null) {
                if (OperatingSystemEnum.WINDOWS.equals(operatingSystem)) {
                    bucketName = fileProperties.getWindowsRootPath();
                } else if (OperatingSystemEnum.MAC.equals(operatingSystem)) {
                    bucketName = fileProperties.getMacRootPath();
                } else {
                    bucketName = fileProperties.getLinuxRootPath();
                }
                cdnHost = fileProperties.getCdnHost();
            }
            if (bucketName == null) {
                log.warn("File root path is null. use '/' is root");
                //默认是根路径
                bucketName = "/";
            }
            if (cdnHost == null) {
                log.warn("File cdnHost is null.");
            }
            osTemplate.setCdnHost(cdnHost);
    
            //设置存储名字
            osTemplate.setBucketName(bucketName);
            //配置文件
            osTemplate.setOsConfigProperties(osConfigProperties);
            return osTemplate;
        }
    }
    

    2.6 工具类

    @Slf4j
    public abstract class IOUtil {
    
    
        /**
         * 输入流转换为输出流
         *
         * @param is 输入流
         * @return 输出流
         */
        public static ByteArrayOutputStream convertInputStream(InputStream is) {
            final byte[] by = new byte[1024];
            ByteArrayOutputStream data = new ByteArrayOutputStream();
            try {
                // 将内容读取内存中
                int len;
                while ((len = is.read(by)) != -1) {
                    data.write(by, 0, len);
                }
            } catch (IOException e) {
                log.error("convertInputStream IO Exception", e);
            }
            return data;
        }
    
        /**
         * base64转化为byte[]字节流
         *
         * @param base64Str 照片的base64
         * @return 字节流
         */
        public static byte[] base64ToBytes(String base64Str) {
            if (StringUtils.isBlank(base64Str)) {
                throw new SealOsException("base64Str is blank!");
            }
            return Base64.decodeBase64(base64Str);
        }
    
        /**
         * 获取文件输入流
         *
         * @param file 文件对象
         * @return 文件输入流对象
         */
        public static InputStream getInputStream(File file) {
            FileInputStream fin;
            try {
                fin = new FileInputStream(file);
            } catch (FileNotFoundException e) {
                if (log.isDebugEnabled()) {
                    log.debug(String.valueOf(e));
                }
                String msg = "找不到指定的文件[" + file.getName() + "]。";
                if (log.isDebugEnabled()) {
                    log.debug(msg);
                }
                throw new SealOsException(msg, e);
            }
            return fin;
        }
    
        /**
         * 获取当前系统的操作系统类型
         */
        public static OperatingSystemEnum getOperatingSystem() {
            if (System.getProperty("os.name").toUpperCase().contains("WINDOWS")) {
                return OperatingSystemEnum.WINDOWS;
            } else if (System.getProperty("os.name").toUpperCase().contains("MAC")) {
                return OperatingSystemEnum.MAC;
            } else {
                return OperatingSystemEnum.LINUX;
            }
        }
    
        /**
         * 文件后缀
         *
         * @param fileName 文件名或者文件路径
         * @return 后缀类型
         */
        public static String getFileSuffix(String fileName) {
            if (fileName == null) {
                return null;
            }
            return fileName.substring(fileName.lastIndexOf("."));
        }
    
        /**
         * 获取文件名
         */
        public static String getFileName(String filePath) {
            if (filePath == null) {
                return null;
            }
            File file=new File(filePath);
            return file.getName();
        }
    
        /**
         * 获取目录
         */
        public static String getDirName(String filePath) {
            if (filePath == null) {
                return null;
            }
            File file=new File(filePath);
            return file.getParent();
        }
    
    
    }
    
    public abstract class OkHttpUtil {
    
        /**
         * 最大连接时间
         */
        public final static int CONNECTION_TIMEOUT = 15;
    
        public final static Logger logger = LoggerFactory.getLogger(OkHttpUtil.class);
    
        /**
         * client
         * 配置重试
         */
        private final static OkHttpClient HTTP_CLIENT = new OkHttpClient.Builder()
                .connectTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
                .build();
    
        /**
         * get请求,无需转换对象
         *
         * @param url 链接
         * @return 响应信息
         */
        public static ByteArrayOutputStream get(String url) {
            try {
                Request request = new Request.Builder().url(url).build();
                Response response = HTTP_CLIENT.newCall(request).execute();
    
                if (response.isSuccessful() && response.body() != null) {
                    InputStream inputStream = response.body().byteStream();
                    return IOUtil.convertInputStream(inputStream);
                }
            } catch (Exception e) {
                logger.error("执行get请求,url: {} 失败!", url, e);
                throw new SealOsException(e);
            }
            return null;
        }
    }
    

    2.7 异常类

    public class OsException extends RuntimeException {
    
    
        public OsException() {
        }
    
        public OsException(String message) {
            super(message);
        }
    
        public OsException(String message, Throwable cause) {
            super(message, cause);
        }
    
        public OsException(Throwable cause) {
            super(cause);
        }
    
        public OsException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
            super(message, cause, enableSuppression, writableStackTrace);
        }
    }
    

    相关文章

      网友评论

        本文标题:SpringBoot2.x整合(cos,oss,本地挂载盘)文件

        本文链接:https://www.haomeiwen.com/subject/onbbtltx.html