栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

实现一个文件存储(本地,OSS,FastDFS)的Spring Boot的starter

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

实现一个文件存储(本地,OSS,FastDFS)的Spring Boot的starter

自定义starter

自己实现一个文件存储(本地存储,阿里云OSS,FastDFS)的Spring Boot的starter

一、了解SpringBoot starter机制

SpringBoot中的starter是一种非常重要的机制,能够抛弃以前繁杂的配置,将其统一集成进starter,应用者只需要在maven中引入starter依赖,SpringBoot就能自动扫描到要加载的信息并启动相应的默认配置。starter让我们摆脱了各种依赖库的处理,需要配置各种信息的困扰。SpringBoot会自动通过classpath路径下的类发现需要的Bean,并注册进IOC容器。SpringBoot提供了针对日常企业应用研发各种场景的spring-boot-starter依赖模块。所有这些依赖模块都遵循着约定成俗的默认配置,并允许我们调整这些配置,即遵循“约定大于配置”的理念。

命名规范

官方命名:

  • 前缀:spring-boot-starter-xxx
  • 比如:spring-boot-starter-web

自定义命名:

  • xxx-spring-boot-starter
  • 比如:mybatis-spring-boot-starter
二、新建一个maven工程

参照官方约定的命名规则:file-storage-spring-boot-starter

项目工程目录

pom.xml



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.2.11.RELEASE
        
    
    com.feige
    file-storage-spring-boot-starter
    1.0

    
        8
        8
        3.13.1
        1.27.2
        1.4
        5.7.13
    

    
        
            org.springframework.boot
            spring-boot-configuration-processor
            true
        
        
            org.springframework.boot
            spring-boot-starter
        

        
        
            com.github.tobato
            fastdfs-client
            ${fastdfs.version}
        

        
        
            com.aliyun.oss
            aliyun-sdk-oss
            ${aliyun-oss.version}
        

        
            commons-fileupload
            commons-fileupload
            ${commons-fileupload.version}
        

        
            cn.hutool
            hutool-all
            ${hutool.version}
        
    


package com.feige.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;


@ConfigurationProperties(prefix = "aliyun.oss")
public class AliyunOssProperties {

    private  String bucketName;

    private  String endpoint;

    public String bucketUrl;

    

    private String accessKeyId;

    private String accessKeySecret;


    public String getBucketName() {
        return bucketName;
    }

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

    public String getEndpoint() {
        return endpoint;
    }

    public void setEndpoint(String endpoint) {
        this.endpoint = endpoint;
    }

    public String getBucketUrl() {
        return bucketUrl;
    }

    public void setBucketUrl(String bucketUrl) {
        this.bucketUrl = bucketUrl;
    }

    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;
    }
}
package com.feige.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;


@ConfigurationProperties(prefix = "feige.storage.local")
public class LocalStorageProperties {

    private String path;

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }
}
package com.feige.service;

import com.feige.pojo.FSInfo;
import com.feige.pojo.UploadInfo;

import javax.validation.constraints.NotNull;
import java.io.InputStream;


public interface FileStorage {

    
    FSInfo upload(@NotNull UploadInfo uploadInfo);


    
    default InputStream getFileInputStream(@NotNull String objectName) {
        return null;
    }

}

package com.feige.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
import com.feige.service.FileStorage;
import com.feige.pojo.FSInfo;
import com.feige.pojo.UploadInfo;
import com.feige.properties.AliyunOssProperties;
import com.feige.utils.FSUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;


public class AliyunOssFileStorageImpl implements FileStorage {

    Logger logger = LoggerFactory.getLogger(AliyunOssFileStorageImpl.class);

    private final AliyunOssProperties aliyunOssProperties;

    public AliyunOssFileStorageImpl(AliyunOssProperties aliyunOssProperties) {
        this.aliyunOssProperties = aliyunOssProperties;
    }

    
    @Override
    public FSInfo upload(UploadInfo uploadInfo) {
        OSS ossClient = null;
        try {
            ossClient = new OSSClientBuilder()
                    .build(aliyunOssProperties.getEndpoint(), aliyunOssProperties.getAccessKeyId(), aliyunOssProperties.getAccessKeySecret());
            // 上传文件到指定的存储空间(bucketName)并将其保存为指定的文件名称(objectName)。
            String group = uploadInfo.isEnableDatePath() ? FSUtils.joinFileName() : "";
            ossClient.putObject(aliyunOssProperties.getBucketName(), group + File.separator + uploadInfo.getFileName(), uploadInfo.getInputStream());
            FSInfo fsInfo = new FSInfo();
            fsInfo.setPath(uploadInfo.getFileName());
            fsInfo.setGroup(group);
            logger.info("{}文件上传成功",uploadInfo.getFileName());
            return fsInfo;
            // 关闭OSSClient。
        } catch (Exception e) {
            logger.error(e.getMessage());
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return null;
    }

    
    @Override
    public InputStream getFileInputStream(String objectName) {
        OSS ossClient = new OSSClientBuilder().build(aliyunOssProperties.getEndpoint(), aliyunOssProperties.getAccessKeyId(), aliyunOssProperties.getAccessKeySecret());
        try {
            OSSObject object = ossClient.getObject(aliyunOssProperties.getBucketName(), objectName);
            return object.getObjectContent();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            ossClient.shutdown();
        }
        throw new RuntimeException("下载文件出错");
    }



}
package com.feige.service.impl;

import com.feige.service.FileStorage;
import com.feige.pojo.FSInfo;
import com.feige.pojo.UploadInfo;
import com.github.tobato.fastdfs.domain.fdfs.metaData;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.HashSet;
import java.util.Set;


public class FastDfsFileStorageImpl implements FileStorage {

    Logger logger = LoggerFactory.getLogger(FastDfsFileStorageImpl.class);

    private final FastFileStorageClient fastFileStorageClient;

    public FastDfsFileStorageImpl(FastFileStorageClient fastFileStorageClient) {
        this.fastFileStorageClient = fastFileStorageClient;
    }


    @Override
    public FSInfo upload(UploadInfo uploadInfo) {
        Set metaData = uploadInfo.getmetaDataSet();
        if (metaData == null){
            metaData = new HashSet<>();
        }
        String objectName = uploadInfo.getFileName() + "." + uploadInfo.getFileExtName();
        metaData.add(new metaData("fileName", objectName));
        StorePath storePath = fastFileStorageClient.uploadFile(uploadInfo.getInputStream(), uploadInfo.getFileSize(), uploadInfo.getFileExtName(), metaData);
        FSInfo fsInfo = new FSInfo();
        fsInfo.setPath(storePath.getPath());
        fsInfo.setGroup(storePath.getGroup());
        logger.info("{}文件上传成功",uploadInfo.getFileName());
        return fsInfo;
    }

    @Override
    public InputStream getFileInputStream(String objectName) {
        int indexOf = objectName.lastIndexOf("/");
        if (indexOf != -1){
            String group = objectName.substring(indexOf + 1);
            String path = objectName.substring(0,indexOf + 1);
            byte[] bytes = fastFileStorageClient.downloadFile(group, path, new DownloadByteArray());
            return new ByteArrayInputStream(bytes);
        }
        throw new IllegalArgumentException("FastDFS下载文件名必须含group和文件名");
    }
}
package com.feige.service.impl;

import com.feige.service.FileStorage;
import com.feige.pojo.FSInfo;
import com.feige.pojo.UploadInfo;
import com.feige.properties.LocalStorageProperties;
import com.feige.utils.FSUtils;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;


public class LocalFileStorageImpl implements FileStorage {

    Logger logger = LoggerFactory.getLogger(LocalFileStorageImpl.class);

    private final LocalStorageProperties localStorageProperties;

    public LocalFileStorageImpl(LocalStorageProperties localStorageProperties) {
        this.localStorageProperties = localStorageProperties;
    }

    @Override
    public FSInfo upload(UploadInfo uploadInfo) {
        String group = uploadInfo.isEnableDatePath() ? File.separator + FSUtils.joinFileName() : "";
        try {
            FileUtils.copyInputStreamToFile(uploadInfo.getInputStream(),new File(getPath() + group + File.separator + uploadInfo.getFileName()));
        } catch (IOException e) {
            e.printStackTrace();
        }
        FSInfo fsInfo = new FSInfo();
        fsInfo.setPath(uploadInfo.getFileName());
        fsInfo.setGroup(group);
        logger.info("{}文件上传成功",uploadInfo.getFileName());
        return fsInfo;
    }

    @Override
    public InputStream getFileInputStream(String objectName) {
        String path = getPath() + objectName;
        try {
            return new ByteArrayInputStream(FileUtils.readFileToByteArray(new File(path)));
        } catch (IOException e) {
            e.printStackTrace();
        }
        throw new RuntimeException("下载文件出错");
    }

    private String getPath(){
        File file = new File("");
        String path = localStorageProperties.getPath();
        if (!path.isEmpty()){
            if (path.charAt(path.length() - 1) != '/'){
                path = path + File.separator;
            }
        }else {
            path = file.getAbsolutePath();
        }
        return path;
    }
}

package com.feige.utils;

import java.io.File;
import java.util.Calendar;


public class FSUtils {

    public static String joinFileName(){
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        return year + File.separator + month + File.separator + day;
    }
}

package com.feige.pojo;

import com.github.tobato.fastdfs.domain.fdfs.metaData;

import java.io.InputStream;
import java.util.Calendar;
import java.util.Set;


public class UploadInfo {

    private InputStream inputStream;
    private Long fileSize;
    private String fileName;
    private boolean enableDatePath;
    private Set metaDataSet;

    public UploadInfo(InputStream inputStream, Long fileSize, String fileName, boolean enableDatePath, Set metaDataSet) {
        this.inputStream = inputStream;
        this.fileSize = fileSize;
        this.fileName = fileName;
        this.enableDatePath = enableDatePath;
        this.metaDataSet = metaDataSet;
    }

    public UploadInfo(InputStream inputStream, Long fileSize, String fileName, boolean enableDatePath) {
        this.inputStream = inputStream;
        this.fileSize = fileSize;
        this.fileName = fileName;
        this.enableDatePath = enableDatePath;
    }

    public UploadInfo() {
    }

    public InputStream getInputStream() {
        return inputStream;
    }

    public void setInputStream(InputStream inputStream) {
        this.inputStream = inputStream;
    }

    public Long getFileSize() {
        return fileSize;
    }

    public void setFileSize(Long fileSize) {
        this.fileSize = fileSize;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getFileExtName() {
        int lastIndexOf = this.fileName.lastIndexOf('.');
        if (lastIndexOf != -1){
            return this.fileName.substring(lastIndexOf + 1);
        }
        return "";
    }


    public Set getmetaDataSet() {
        return metaDataSet;
    }

    public void setmetaDataSet(Set metaDataSet) {
        this.metaDataSet = metaDataSet;
    }

    public boolean isEnableDatePath() {
        return enableDatePath;
    }

    public void setEnableDatePath(boolean enableDatePath) {
        this.enableDatePath = enableDatePath;
    }
}

package com.feige.pojo;



public class FSInfo {

    private String group;

    private String path;

    
    public String getGroup() {
        return this.group;
    }

    public void setGroup(String group) {
        this.group = group;
    }

    
    public String getPath() {
        return this.path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    
    public String getFullPath() {
        return this.group.concat("/").concat(this.path);
    }

}

package com.feige.conf;

import com.feige.service.FileStorage;
import com.feige.service.impl.AliyunOssFileStorageImpl;
import com.feige.service.impl.FastDfsFileStorageImpl;
import com.feige.service.impl.LocalFileStorageImpl;
import com.feige.properties.AliyunOssProperties;
import com.feige.properties.LocalStorageProperties;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration(proxyBeanMethods = false)
public class FileStorageAutoConfiguration {


    @Configuration(
            proxyBeanMethods = false
    )
    @ConditionalOnProperty(
            prefix = "feige.storage",
            name = "type",
            havingValue = "oss"
    )
    @EnableConfigurationProperties(AliyunOssProperties.class)
    public static class EnableAliyunOssConfiguration{

        private final AliyunOssProperties aliyunOssProperties;

        @Autowired
        public EnableAliyunOssConfiguration(AliyunOssProperties aliyunOssProperties) {
            this.aliyunOssProperties = aliyunOssProperties;
        }

        @Bean
        @ConditionalOnMissingBean({FileStorage.class})
        public FileStorage FileStorage(){
            return new AliyunOssFileStorageImpl(this.aliyunOssProperties);
        }


    }


    @Configuration(
            proxyBeanMethods = false
    )
    public static class EnableFastDfsConfiguration{

        private final FastFileStorageClient fastFileStorageClient;

        @Autowired
        public EnableFastDfsConfiguration(FastFileStorageClient fastFileStorageClient) {
            this.fastFileStorageClient = fastFileStorageClient;
        }

        @Bean
        @ConditionalOnMissingBean({FileStorage.class})
        @ConditionalOnProperty(
                prefix = "feige.storage",
                name = "type",
                havingValue = "fastdfs"
        )
        public FileStorage FileStorage(){
            return new FastDfsFileStorageImpl(fastFileStorageClient);
        }
    }


    @Configuration(
            proxyBeanMethods = false
    )
    @ConditionalOnProperty(
            prefix = "feige.storage",
            name = "type",
            havingValue = "local"
    )
    @EnableConfigurationProperties(LocalStorageProperties.class)
    public static class EnableLocalStoreConfiguration{

        private final LocalStorageProperties localStorageProperties;

        @Autowired
        public EnableLocalStoreConfiguration(LocalStorageProperties localStorageProperties) {
            this.localStorageProperties = localStorageProperties;
        }

        @Bean
        @ConditionalOnMissingBean({FileStorage.class})
        public FileStorage FileStorage(){
            return new LocalFileStorageImpl(localStorageProperties);
        }
    }

}

resourcesmeta-INFadditional-spring-configuration-metadata.json

{
  "properties": [
    {
      "name": "aliyun.oss.bucket-name",
      "type": "java.lang.String",
      "description": "阿里云OSS的bucketName.",
      "defaultValue": ""
    },
    {
      "name": "aliyun.oss.endpoint",
      "type": "java.lang.String",
      "description": "阿里云OSS的endpoint.",
      "defaultValue": ""
    },
    {
      "name": "aliyun.oss.bucket-url",
      "type": "java.lang.String",
      "description": "阿里云OSS的bucketUrl.",
      "defaultValue": ""
    },
    {
      "name": "aliyun.oss.access-key-id",
      "type": "java.lang.String",
      "description": "阿里云OSS的accessKeyId.",
      "defaultValue": ""
    },
    {
      "name": "aliyun.oss.access-key-secret",
      "type": "java.lang.String",
      "description": "阿里云OSS的accessKeySecret.",
      "defaultValue": ""
    },{
      "name": "feige.storage.type",
      "type": "java.lang.String",
      "description": "文件存储类型(oss,fastdfs,local),默认为local." ,
      "defaultValue": "local"
    },{
      "name": "feige.storage.local.path",
      "type": "java.lang.String",
      "description": "本地文件保存路径,默认为项目根路径." ,
      "defaultValue": ""
    }
  ]
}

resourcesmeta-INFspring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=
  com.feige.conf.FileStorageAutoConfiguration

打jar包

新建一个SpringBoot项目,导入即可测试


    com.feige
    file-storage-spring-boot-starter
    1.0

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/270102.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号