Spring File Storage文件的对象存储框架基本使用小结

 更新时间:2024年08月19日 10:27:39   作者:墨鸦_Cormorant  
在开发过程当中,会使用到存文档、图片、视频、音频等等,这些都会涉及存储的问题,文件可以直接存服务器,但需要考虑带宽和存储空间,另外一种方式就是使用云存储,这篇文章主要介绍了Spring File Storage文件的对象存储框架基本使用小结,需要的朋友可以参考下

概述

本文仅作为快速入门,深入学习及使用详见官网

云存储

在开发过程当中,会使用到存文档、图片、视频、音频等等,这些都会涉及存储的问题,文件可以直接存服务器,但需要考虑带宽和存储空间,另外一种方式就是使用云存储。目前主流的云存储有阿里云OSS、华为云OBS、七牛云Kodo、腾讯云COS、百度云 BOS、又拍云USS、MinIO 等。

X Spring File Storage 介绍

在 SpringBoot 中通过简单的方式将文件存储到 本地、FTP、SFTP、WebDAV、谷歌云存储、阿里云OSS、华为云OBS、七牛云Kodo、腾讯云COS、百度云 BOS、又拍云USS、MinIO、 AWS S3、金山云 KS3、美团云 MSS、京东云 OSS、天翼云 OOS、移动云 EOS、沃云 OSS、 网易数帆 NOS、Ucloud US3、青云 QingStor、平安云 OBS、首云 OSS、IBM COS、其它兼容 S3 协议的平台。

支持的平台如下图:

快速入门

添加依赖

<dependencies>
    <!-- spring-file-storage 必须要引入 -->
    <dependency>
        <groupId>cn.xuyanwu</groupId>
        <artifactId>spring-file-storage</artifactId>
        <version>2.1.0</version>
    </dependency>
    <!-- 华为云OBS 不使用的情况下可以不引入 -->
    <dependency>
        <groupId>com.huaweicloud</groupId>
        <artifactId>esdk-obs-java</artifactId>
        <version>3.22.12</version>
    </dependency>
    <!-- 阿里云OSS 不使用的情况下可以不引入 -->
    <dependency>
        <groupId>com.aliyun.oss</groupId>
        <artifactId>aliyun-sdk-oss</artifactId>
        <version>3.16.1</version>
    </dependency>

添加配置文件

注:以下配置是 2.1.0 版本的配置

dromara:
  x-file-storage: #文件存储配置
    default-platform: huawei-obs-1 #默认使用的存储平台
    thumbnail-suffix: ".min.jpg" #缩略图后缀,例如【.min.jpg】【.png】
    # 对应平台的配置写在这里,注意缩进要对齐
    huawei-obs:
      - platform: huawei-obs-1 # 存储平台标识
        enable-storage: true  # 启用存储。只有状态开启才会被识别到
        access-key: ??
        secret-key: ??
        end-point: ??
        bucket-name: ??
        domain: ?? # 访问域名,注意“/”结尾,例如:http://abc.obs.com/
        base-path: test/ # 基础路径
    # 本地存储(升级版)
    local-plus:
      - platform: local-plus-1 # 存储平台标识
        enable-storage: true  #启用存储
        enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高)
        domain: http://127.0.0.1:8080/file/ # 访问域名,例如:“http://127.0.0.1:8030/file/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名
        base-path: local-plus/ # 基础路径
        path-patterns: /file/** # 访问路径
        storage-path: D:/Temp/ # 存储路径

编码

显式的开启文件上传功能

在启动类上加上@EnableFileStorage注解

@EnableFileStorage
@SpringBootApplication
public class SpringFileStorageTestApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringFileStorageTestApplication.class,args);
    }
}

上传

支持 File、MultipartFile、byte[]、InputStream、URL、URI、String、HttpServletRequest,大文件会自动分片上传。

@RestController
public class FileDetailController {
    @Autowired
    private FileStorageService fileStorageService;//注入实列
    /**
     * 上传文件
     */
    @PostMapping("/upload")
    public FileInfo upload(MultipartFile file) {
        return fileStorageService.of(file).upload();
    }
    /**
     * 上传文件,成功返回文件 url
     */
    @PostMapping("/upload2")
    public String upload2(MultipartFile file) {
        FileInfo fileInfo = fileStorageService.of(file)
                .setPath("upload/") //保存到相对路径下,为了方便管理,不需要可以不写
                .setObjectId("0")   //关联对象id,为了方便管理,不需要可以不写
                .setObjectType("0") //关联对象类型,为了方便管理,不需要可以不写
                .putAttr("role","admin") //保存一些属性,可以在切面、保存上传记录、自定义存储平台等地方获取使用,不需要可以不写
                .upload();  //将文件上传到对应地方
        return fileInfo == null ? "上传失败!" : fileInfo.getUrl();
    }
    /**
     * 上传图片,成功返回文件信息
     * 图片处理使用的是 https://github.com/coobird/thumbnailator
     */
    @PostMapping("/upload-image")
    public FileInfo uploadImage(MultipartFile file) {
        return fileStorageService.of(file)
                .image(img -> img.size(1000,1000))  //将图片大小调整到 1000*1000
                .thumbnail(th -> th.size(200,200))  //再生成一张 200*200 的缩略图
                .upload();
    }
    /**
     * 上传文件到指定存储平台,成功返回文件信息
     */
    @PostMapping("/upload-platform")
    public FileInfo uploadPlatform(MultipartFile file) {
        return fileStorageService.of(file)
                .setPlatform("aliyun-oss-1")    //使用指定的存储平台
                .upload();
    }
    /**
     * 直接读取 HttpServletRequest 中的文件进行上传,成功返回文件信息
     * 使用这种方式有些注意事项,请查看文档 基础功能-上传 章节
     */
    @PostMapping("/upload-request")
    public FileInfo uploadPlatform(HttpServletRequest request) {
        return fileStorageService.of(request).upload();
    }
}

文件是否存在、下载、删除

//手动构造文件信息,可用于其它操作
FileInfo fileInfo = new FileInfo()
        .setPlatform("huawei-obs-1")
        .setBasePath("test/")
        .setPath("aa/")
        .setFilename("image.png")
        .setThFilename("image.png.min.jpg");
//文件是否存在
boolean exists = fileStorageService.exists(fileInfo);
//下载
byte[] bytes = fileStorageService.download(fileInfo).bytes();
// 下载到文件
fileStorageService.download(fileInfo).file("C:\\a.jpg");
// 下载缩略图
fileStorageService.downloadTh(fileInfo).file("C:\\th.jpg");
//删除
fileStorageService.delete(fileInfo);
// 如果将文件记录保存到数据库中,还可以更方便的根据 URL 进行操作
//直接从数据库中获取 FileInfo 对象,更加方便执行其它操作
FileInfo fileInfo = fileStorageService.getFileInfoByUrl("https://abc.def.com/test/aa/image.png");
//文件是否存在
boolean exists = fileStorageService.exists("https://abc.def.com/test/aa/image.png");
//下载
byte[] bytes = fileStorageService.download("https://abc.def.com/test/aa/image.png").bytes();
//删除
fileStorageService.delete("https://abc.def.com/test/aa/image.png");

监听器

// 下载文件 显示进度
fileStorageService.download(fileInfo).setProgressMonitor(new ProgressListener() {
    @Override
    public void start() {
        System.out.println("下载开始");
    }
    @Override
    public void progress(long progressSize,long allSize) {
        System.out.println("已下载 " + progressSize + " 总大小" + allSize);
    }
    @Override
    public void finish() {
        System.out.println("下载结束");
    }
}).file("C:\\a.jpg");

切面

工具还提供了每种操作的切面,可以在每个动作的前后进行干预,比如打日志,实现 FileStorageAspect 类重写对应动作的 xxxAround 方法。

/**
 * 使用切面打印文件上传和删除的日志
 */
@Slf4j
@Component
public class LogFileStorageAspect implements FileStorageAspect {
    /**
     * 上传,成功返回文件信息,失败返回 null
     */
    @Override
    public FileInfo uploadAround(UploadAspectChain chain, FileInfo fileInfo, UploadPretreatment pre, FileStorage fileStorage, FileRecorder fileRecorder) {
        log.info("上传文件 before -> {}",fileInfo);
        fileInfo = chain.next(fileInfo,pre,fileStorage,fileRecorder);
        log.info("上传文件 after -> {}",fileInfo);
        return fileInfo;
    }
}

表设计

-- mysql
DROP TABLE IF EXISTS `file_detail`;
CREATE TABLE `file_detail`
(
    `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '文件id',
    `url` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '文件访问地址',
    `size`  bigint(20) NULL DEFAULT NULL COMMENT '文件大小,单位字节',
    `filename` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件名称',
    `original_filename` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '原始文件名',
    `base_path` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '基础存储路径',
    `path` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '存储路径',
    `ext` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci  NULL DEFAULT NULL COMMENT '文件扩展名',
    `content_type` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'MIME类型',
    `platform` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci  NULL DEFAULT NULL COMMENT '存储平台',
    `th_url` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '缩略图访问路径',
    `th_filename` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '缩略图名称',
    `th_size` bigint(20) NULL DEFAULT NULL COMMENT '缩略图大小,单位字节',
    `th_content_type` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '缩略图MIME类型',
    `object_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件所属对象id',
    `object_type` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件所属对象类型,例如用户头像,评价图片',
    `attr` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '附加属性',
    `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  CHARACTER SET = utf8
  COLLATE = utf8_general_ci COMMENT = '文件记录表'
  ROW_FORMAT = Dynamic;
-- postgre 自定义
create table if not exists "file_detail" (
    id VARCHAR(255) not null,
    url VARCHAR(255) not null,
    "size" BIGINT null,
    filename VARCHAR(255) null,
    original_filename VARCHAR(255) null,
    base_path VARCHAR(255) null,
    "path" VARCHAR(255) null,
    ext VARCHAR(255) null,
    content_type VARCHAR(255) null,
    platform VARCHAR(255) null,
    th_url VARCHAR(255) null,
    th_filename VARCHAR(255) null,
    th_size bigint null,
    th_content_type VARCHAR(255) null,
    object_id VARCHAR(255) null,
    object_type VARCHAR(255) null,
    attr VARCHAR(255) null,
    create_time TIMESTAMP null,
    project_id UUID null,
    tenant_id UUID null,
    primary key ("id")
    );
-- Column comments
COMMENT ON TABLE file_detail IS '文件记录表';
COMMENT ON COLUMN public.file_detail.id IS '主键';
COMMENT ON COLUMN public.file_detail.url IS '文件访问地址';
COMMENT ON COLUMN public.file_detail."size" IS '文件大小,单位字节';
COMMENT ON COLUMN public.file_detail.filename IS '文件名称';
COMMENT ON COLUMN public.file_detail.original_filename IS '原始文件名';
COMMENT ON COLUMN public.file_detail.base_path IS '基础存储路径';
COMMENT ON COLUMN public.file_detail."path" IS '存储路径';
COMMENT ON COLUMN public.file_detail.ext IS '文件扩展名';
COMMENT ON COLUMN public.file_detail.content_type IS 'MIME类型';
COMMENT ON COLUMN public.file_detail.platform IS '存储平台';
COMMENT ON COLUMN public.file_detail.th_url IS '缩略图访问路径';
COMMENT ON COLUMN public.file_detail.th_filename IS '缩略图名称';
COMMENT ON COLUMN public.file_detail.th_size IS '缩略图大小,单位字节';
COMMENT ON COLUMN public.file_detail.th_content_type IS '缩略图MIME类型';
COMMENT ON COLUMN public.file_detail.object_id IS '文件所属对象id';
COMMENT ON COLUMN public.file_detail.object_type IS '文件所属对象类型,例如用户头像,评价图';
COMMENT ON COLUMN public.file_detail.attr IS '附加属性';
COMMENT ON COLUMN public.file_detail.create_time IS '创建时间';
COMMENT ON COLUMN public.file_detail.project_id IS '项目id';
COMMENT ON COLUMN public.file_detail.tenant_id IS '租户id';

参考资料

Springboot 中快速完成文件上传,整合多平台神器

到此这篇关于Spring File Storage(文件的对象存储)框架基本使用指南的文章就介绍到这了,更多相关Spring File Storage内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java微信开发API第四步 微信自定义个性化菜单实现

    java微信开发API第四步 微信自定义个性化菜单实现

    这篇文章主要为大家详细介绍了java微信开发API第四步,自定义菜单以及个性化菜单实现 ,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • Spring data JPA只查询部分字段问题及解决

    Spring data JPA只查询部分字段问题及解决

    这篇文章主要介绍了Spring data JPA只查询部分字段问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • java实习--每天打卡十道面试题!

    java实习--每天打卡十道面试题!

    临近秋招,备战暑期实习,祝大家每天进步亿点点!本篇文章准备了十道java的常用面试题,希望能够给大家提供帮助,最后祝大家面试成功,进入自己心仪的大厂
    2021-06-06
  • Java 报错 java.util.ConcurrentModificationException: null 的原因及解决方案

    Java 报错 java.util.ConcurrentModificationException: null 

    这篇文章主要介绍了Java 报错 java.util.ConcurrentModificationException: null 的原因和解决方案,这个异常通常在多线程环境下出现,意味着在迭代过程中,集合或者映射的结构发生了变化,本文分享完美解决方案,需要的朋友可以参考下
    2023-07-07
  • Java字符串常量池示例详解

    Java字符串常量池示例详解

    作为最基础的引用数据类型,Java设计者为 String 提供了字符串常量池以提高其性能,下面这篇文章主要给大家介绍了关于Java字符串常量池的相关资料,需要的朋友可以参考下
    2021-08-08
  • 深入理解Java运行时数据区_动力节点Java学院整理

    深入理解Java运行时数据区_动力节点Java学院整理

    这篇文章主要介绍了Java运行时数据区的相关知识,非常不错,具有参考借鉴价值,需要的朋友参考下吧
    2017-06-06
  • Java操作数据库(行级锁,for update)

    Java操作数据库(行级锁,for update)

    这篇文章主要介绍了Java操作数据库(行级锁,for update),文章围绕Java操作数据库的相关资料展开详细内容,需要的小伙伴可以参考一下,希望对你有所帮助
    2021-12-12
  • 利用Java代码实现区块链技术

    利用Java代码实现区块链技术

    这篇文章主要介绍了利用Java代码实现区块链技术,区块链的应用范围几乎无穷无尽,关于区块链是如何运作的,下文来看看具体的内容介绍吧,需要的朋友可以参考一下
    2022-04-04
  • SpringBoot中处理的转发与重定向方式

    SpringBoot中处理的转发与重定向方式

    这篇文章主要介绍了SpringBoot中处理的转发与重定向方式,分别就转发和重定向做了概念解说,结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-11-11
  • 深入解析Java编程中的boolean对象的运用

    深入解析Java编程中的boolean对象的运用

    这篇文章主要介绍了Java编程中的boolean对象的运用,是Java入门学习中的基础知识,需要的朋友可以参考下
    2015-10-10

最新评论