美文网首页JavaitIT必备技能
前后端分离项目,如何优雅实现文件存储?

前后端分离项目,如何优雅实现文件存储?

作者: java菲菲 | 来源:发表于2020-01-02 11:40 被阅读0次

    推荐阅读一下下:

    1. 备战春招之MySQL:历年高频面试真题梳理及众多学习笔记和书籍
    2. 拼多多三面惨败,java中间件、数据库与spring框架,答不上...

    结合SpringBoot使用

    接下来我们将结合SpringBoot来实现一个完整的图片上传与删除操作。

    • 上传流程示意图:
    image.png
    • 在pom.xml中添加MinIO的相关依赖:
    <!--MinIO JAVA SDK-->
    <dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>3.0.10</version>
    </dependency>
    
    • 在SpringBoot中开启文件上传功能,需要在application.yml添加如下配置:
    spring:
      servlet:
        multipart:
          enabled: true #开启文件上传
          max-file-size: 10MB #限制文件上传大小为10M
    复制代码
    
    • 添加一个MinioController控制器用于实现文件的上传和删除操作:
    /**
     * Created by macro on 2019/12/25.
     */
    @Api(tags = "MinioController", description = "MinIO对象存储管理")
    @Controller
    @RequestMapping("/minio")
    public class MinioController {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(MinioController.class);
        @Value("${minio.endpoint}")
        private String ENDPOINT;
        @Value("${minio.bucketName}")
        private String BUCKET_NAME;
        @Value("${minio.accessKey}")
        private String ACCESS_KEY;
        @Value("${minio.secretKey}")
        private String SECRET_KEY;
    
        @ApiOperation("文件上传")
        @RequestMapping(value = "/upload", method = RequestMethod.POST)
        @ResponseBody
        public CommonResult upload(@RequestParam("file") MultipartFile file) {
            try {
                //创建一个MinIO的Java客户端
                MinioClient minioClient = new MinioClient(ENDPOINT, ACCESS_KEY, SECRET_KEY);
                boolean isExist = minioClient.bucketExists(BUCKET_NAME);
                if (isExist) {
                    LOGGER.info("存储桶已经存在!");
                } else {
                    //创建存储桶并设置只读权限
                    minioClient.makeBucket(BUCKET_NAME);
                    minioClient.setBucketPolicy(BUCKET_NAME, "*.*", PolicyType.READ_ONLY);
                }
                String filename = file.getOriginalFilename();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
                // 设置存储对象名称
                String objectName = sdf.format(new Date()) + "/" + filename;
                // 使用putObject上传一个文件到存储桶中
                minioClient.putObject(BUCKET_NAME, objectName, file.getInputStream(), file.getContentType());
                LOGGER.info("文件上传成功!");
                MinioUploadDto minioUploadDto = new MinioUploadDto();
                minioUploadDto.setName(filename);
                minioUploadDto.setUrl(ENDPOINT + "/" + BUCKET_NAME + "/" + objectName);
                return CommonResult.success(minioUploadDto);
            } catch (Exception e) {
                LOGGER.info("上传发生错误: {}!", e.getMessage());
            }
            return CommonResult.failed();
        }
    
        @ApiOperation("文件删除")
        @RequestMapping(value = "/delete", method = RequestMethod.POST)
        @ResponseBody
        public CommonResult delete(@RequestParam("objectName") String objectName) {
            try {
                MinioClient minioClient = new MinioClient(ENDPOINT, ACCESS_KEY, SECRET_KEY);
                minioClient.removeObject(BUCKET_NAME, objectName);
                return CommonResult.success(null);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return CommonResult.failed();
        }
    }
    
    • 在application.yml中对MinIO客户端进行配置:
    # MinIO对象存储相关配置
    minio:
      endpoint: http://192.168.6.132:9090 #MinIO服务所在地址
      bucketName: mall #存储桶名称
      accessKey: minioadmin #访问的key
      secretKey: minioadmin #访问的秘钥
    
    image.png
    • 上传完成后,我们打开MinIO的管理界面可以看到上传后的图片,也可以通过返回的url来访问图片:


      image.png
    • 我们可以调用删除接口来删除该图片,需要注意的是objectName值是存储桶中的图片相对路径,删除文件接口地址:http://localhost:8080/minio/delete
      image.png

    结合Vue使用

    经过上面操作,我们的SpringBoot应用已经可以完成文件上传与删除操作了,接下来我们结合Vue来实现前端上传图片到MinIO中,以mall-admin-web中的代码为例。

    • 我们的SpringBoot应用需要支持跨域请求,否则Vue前端无法进行接口调用,我们先添加一个全局的跨域请求配置:
    /**
     * 全局跨域配置
     * Created by macro on 2019/7/27.
     */
    @Configuration
    public class GlobalCorsConfig {
    
        /**
         * 允许跨域调用的过滤器
         */
        @Bean
        public CorsFilter corsFilter() {
            CorsConfiguration config = new CorsConfiguration();
            //允许所有域名进行跨域调用
            config.addAllowedOrigin("*");
            //允许跨越发送cookie
            config.setAllowCredentials(true);
            //放行全部原始头信息
            config.addAllowedHeader("*");
            //允许所有请求方法跨域调用
            config.addAllowedMethod("*");
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", config);
            return new CorsFilter(source);
        }
    }
    
    • mall-admin-web的文件上传操作主要是在singleUpload.vuemultiUpload.vue中,下面我们以singleUpload.vue的修改为例。

    • 我们需要把原来的OSS上传和现在的MinIO上传做个兼容操作,先在Vue实例的数据对象中添加三个属性:

    image.png
    • 然后根据useOss属性设置el-upload上传组件的提交地址和提交参数:
    image.png
    • el-upload上传文件之前的钩子函数中添加如下代码,对于使用MinIO上传的操作不进行获取OSS上传策略的操作;
    image.png
    • 最后在el-upload文件上传成功的钩子函数中添加如下代码,对于使用MinIO上传的操作直接从返回结果中获取文件url;
    image.png
    • 运行mall-admin-web项目,使用商品分类下的添加功能来测试下文件上传,发现已经可以成功上传,图片也已经可以正常回显:
    image.png

    作者:MacroZheng
    链接:https://juejin.im/post/5e0ca2266fb9a0484a45969c

    相关文章

      网友评论

        本文标题:前后端分离项目,如何优雅实现文件存储?

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