03
2024
07
14:53:23

X Spring File Storage居然支持这么多云存储平台,还不赶紧过来围观一下吗?


具体怎么用起来我是没搞懂,看起来很高大上。


感觉有点东西呢。因为穷啊,我只好本地搭建一个minio文件服务器来演示下了,哈哈。

3 搭建Minio文件服务器

环境说明:

  • 虚拟机中安装的Ubuntu 18.04.4 LTS版本的系统,

  • Docker version 20.10.21, build baeda1f

我已经默认各位知道Docker怎么用了哈,接下来直接今入安装步骤,如果不清楚Docker是何物的请问下度娘。

3.1 拉取Minio镜像

docker pull quay.io/minio/minio

3.2 在/etc/default目录下创建一个配置文件minioConfig.env

vim /etc/default/minioConfig.env

配置文件内容如下

# MINIO_ROOT_USER and MINIO_ROOT_PASSWORD sets the root account for the MinIO server.
# This user has unrestricted permissions to perform S3 and administrative API operations on any resource in the deployment.
# Omit to use the default values 'minioadmin:minioadmin'.
# MinIO recommends setting non-default values as a best practice, regardless of environment

MINIO_ROOT_USER=minio
MINIO_ROOT_PASSWORD=minio123456

# MINIO_VOLUMES sets the storage volume or path to use for the MinIO server.

MINIO_VOLUMES="/mnt/data/minio"

# MINIO_SERVER_URL sets the hostname of the local machine for use with the MinIO Server
# MinIO assumes your network control plane can correctly resolve this hostname to the local machine

MINIO_ROOT_USER: 它是管理页面登录的用户名

MINIO_ROOT_PASSWORD:管理页面登录的密码

MINIO_VOLUMES:容器持久化映射目录,这里是/mnt/data/minio,如果目录不存在请手动创建一下

创建命令如下:

mkdir -p /mnt/data/minio

以上内容配置完成保存退出即可。

3.3 创建容器

docker run -dt  \
  -p 9000:9000 -p 9090:9090 \
  -v /mnt/data/minio:/mnt/data \
  -v /etc/default/minioConfig.env:/etc/config.env  \
  -e "MINIO_CONFIG_ENV_FILE=/etc/config.env" \
  --name "minio_local" --restart=always \
  quay.io/minio/minio  server --console-address ":9090"

3.4 访问文件服务器

浏览器输入:192.168.158.128:9090/

输入刚才文件中配置的账号和密码即可登录。

3.5 创建存储桶

存储桶相当于电脑中文件存放的一个目录,根据如下图指示创建即可。

接下来设置访问策略,点击左侧Object Browser,可以看到刚才创建好的存储桶,继续点击

点击右上角设置按钮,在弹出的新窗口将Access Policy下面的private设置成public,这样图片就可以正常访问了。

3.6 创建秘钥

秘钥用于系统后端通过接口形式访问文件服务器的凭证,根据如下面所示创建即可。

点击右侧的创建之后弹出下面的窗口,然后点击Create,它会让你把秘钥凭证下载下来本地保存。

保存完成打开的文件如上图所示。好了,到此为止minio的文件服务器已搭建完毕。

4 springboot项目中集成

4.1 添加依赖

pom文件中添加如下依赖

 <properties>
        <xuyanwu.version>0.7.0</xuyanwu.version>
        <minio.version>8.4.3</minio.version>
        <okhttp3.version>4.9.0</okhttp3.version>
    </properties>


    <dependencies>

        <!-- spring-file-storage 必须要引入 -->
        <dependency>
            <groupId>cn.xuyanwu</groupId>
            <artifactId>spring-file-storage</artifactId>
            <version>${xuyanwu.version}</version>
        </dependency>

        <!-- MinIO 不使用的情况下可以不引入 -->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>${minio.version}</version>
        </dependency>

        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
        </dependency>

这里需要说明下,minio自动依赖的okhttp版本太低,所以需要重新依赖一个版本高的,不然上传图片会报错。

4.2 添加配置文件

yml配置文件中添加如下内容,9090端口是浏览器访问的,9000是通过api访问的,这里要搞清楚,不要搞错了。不然无法上传图片。

  file-storage:
    default-platform: minio-1
    minio:
      - platform: minio-1 # 存储平台标识
        enable-storage: true  # 启用存储
        access-key: bBMoML6jNAyYZfbB
        secret-key: FR9bvT7k5w1YxcGtqjVLaHMPhDIlXsrF
        end-point: http://192.168.158.128:9000
        bucket-name: bdwc
        domain: http://192.168.158.128:9000/bdwc/

注意,该配置在spring标签的下一级

4.3 文件记录表

这里也要多说下,因为项目原因,此表明与官网给的表明是不一样的,而且id属性我也做了修改,所以在做ORM的时候,生成对应的java类也不一样,这里先做个铺垫,后面会做说明。

这个表用于文件记录存储的表。

create table if not exists bdwc_files(
    id                bigint auto_increment comment '文件id'
        primary key,
    url               varchar(512) not null comment '文件访问地址',
    size              bigint       null comment '文件大小,单位字节',
    filename          varchar(256) not null comment '文件名称',
    original_filename varchar(256) null comment '原始文件名',
    base_path         varchar(256) null comment '基础存储路径',
    path              varchar(256) null comment '存储路径',
    ext               varchar(32)  null comment '文件扩展名',
    content_type      varchar(32)  null comment 'MIME类型',
    platform          varchar(32)  null comment '存储平台',
    th_url            varchar(512) null comment '缩略图访问路径',
    th_filename       varchar(256) null comment '缩略图名称',
    th_size           bigint       null comment '缩略图大小,单位字节',
    th_content_type   varchar(32)  null comment '缩略图MIME类型',
    object_id         varchar(32)  null comment '文件所属对象id',
    object_type       varchar(32)  null comment '文件所属对象类型,例如用户头像,评价图片',
    attr              text         null comment '附加属性',
    create_time       datetime     null comment '创建时间',
    constraint bdwc_file_detail_filename_uindex
        unique (filename),
    constraint bdwc_file_detail_url_uindex
        unique (url))
    comment '文件列表';

4.4 文件上传接口

    /**     * 上传文件     */
    @PostMapping("/uploads")
    public AjaxResult add(List<MultipartFile> files) {
        try {
            List<String> urls = new ArrayList<String>();
            List<String> fileNames = new ArrayList<String>();
            List<String> newFileNames = new ArrayList<String>();
            List<String> originalFilenames = new ArrayList<String>();
            for (MultipartFile file : files) {
                //上传文件并返回文件信息                FileInfo fileInfo = fileStorageService.of(file)
                        .setPath(DateUtils.dateTime() + "/") //保存到相对路径下,为了方便管理,不需要可以不写                        .upload();  //将文件上传到对应地方                log.info("fileInfo={}", fileInfo.toString());
                String fileName = fileInfo.getFilename();
                String url = fileInfo.getUrl();
                urls.add(url);
                fileNames.add(fileName);
                newFileNames.add(fileInfo.getFilename());
                originalFilenames.add(fileInfo.getOriginalFilename());
            }
            AjaxResult ajax = AjaxResult.success();
            ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
            ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
            ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
            ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
            return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

这里说明下,核心上传处理的方法是下面这段代码

 //上传文件并返回文件信息
                FileInfo fileInfo = fileStorageService.of(file)
                        .setPath(DateUtils.dateTime() + "/") //保存到相对路径下,为了方便管理,不需要可以不写
                        .upload();  //将文件上传到对应地方

那有人会问,就这么简单就完成了吗?当然不是,不知道各位在集成的时候,启动项目,然后启动日志里面是不是又这么一句话:未找到FileRecorder,除上传以外的操作无法正常使用,所以我们还得写个FileRecorder。

@Slf4j@Servicepublic class FileDetailService implements FileRecorder {

    @Autowired
    private IFilesService filesService;

    //插入文件记录    @Override
    public boolean record(FileInfo fileInfo) {
        Files file = new Files();
        BeanUtils.copyProperties(fileInfo, file, "id");
        return filesService.insertFiles(file) > 0 ? true : false;
    }

    //根据文件URL获取文件    @Override
    public FileInfo getByUrl(String url) {
        log.debug("getByUrl");
        Files files = filesService.selectFilesByUrl(url);
        FileInfo fileInfo = new FileInfo();
        BeanUtils.copyProperties(files, fileInfo, "id");
        return fileInfo;
    }

    //删除文件    @Override
    public boolean delete(String url) {
        log.debug("delete={}",url);
        return filesService.deleteFilesByUrl(url) > 0 ? true : false;
    }}

我们写个类继承FileRecorder,然后重写三个方法record,getByurl,delete。

record :该方法是将文件记录插入到表中。

getByurl : 该方法是通过文件url查询文件记录。

delete: 该方法会删除文件记录。

filesService是我自己的方法,也就是操作数据库的服务,各位可根据自己情况自行实现。

前面我说我的ORM映射类与官网的不一样,我的是Files,官方的是FileInfo,而且FileRecorder中限制就是使用FileInfo,所以这里我使用了如下代码做了属性值的转换,最后使用自己的类做的插入。

BeanUtils.copyProperties(fileInfo, file, "id");

这个方法大家应该见过吧,后面一个参数id是忽略转换,因为我的表id与FileInfo的id不一样。

当我们上传文件时,执行下面代码,这时候FileRecorder中的record方法会调用,然后文件记录就产生了,图片也上传到云端了。

FileInfo fileInfo = fileStorageService.of(file)
                        .setPath(DateUtils.dateTime() + "/") //保存到相对路径下,为了方便管理,不需要可以不写
                        .upload();  //将文件上传到对应地方


4.5 文件上传演示

这里我使用富文本编辑器的图片上传作为案例上传了一张图片

看下文件列表中的数据

再来看下minio文件服务器中

4.6 文件删除

   /**     * 删除文件     */
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        for (Long id : ids) {
            fileStorageService.delete(filesService.selectFilesById(id).getUrl());
        }
        return AjaxResult.success();
    }

当执行fileStorageService.delete(filesService.selectFilesById(id).getUrl());时,FileRecorder中的delete会调用,此时文件与记录会一并删除。

它的这些功能是通过切面完成的,看源码可以知道,以下截图说明

这是上传的切面

这是删除的切面

可以看到执行的时候FileRecorder参数是一直存在的,只有重新它里面的方法,接入我们自己的逻辑才可以实现简单的删除下载功能。

5 完结

就先写到这里吧,大家下面可以自己尝试下。下面我把该开源项目的地址贴到下面,各位可以研究看下。




推荐本站淘宝优惠价购买喜欢的宝贝:

image.png

本文链接:https://hqyman.cn/post/6934.html 非本站原创文章欢迎转载,原创文章需保留本站地址!

分享到:
打赏





休息一下~~


« 上一篇 下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

请先 登录 再评论,若不是会员请先 注册

您的IP地址是: