当前位置:   article > 正文

springboot+minio文件存储初尝试_springboot集成minio downloadobject

springboot集成minio downloadobject

文件服务算是一个基础服务了,比较专业的组件有FastDFS,也可以采用基本的保存在本地的文件上传方式,但是其安全性不高。对于中小公司来说,可以直接购买云存储服务,当然也可以自己搭建,下面就聊聊springboot集成文件服务组件MinIO,看看这个组件带来了那些惊喜。
MinIO是一个基于Apache License v2.0开源协议的对象存储服务,非常合适存储大容量非结构化的数据,如图片、视频、日志文件等,一个对象文件的大小可以是几KB到5T不等。MinIO是一个轻量级的服务,类似redis、mysql,可以很方便的和其他应用结合,并且自带非常方便的可视化界面,让人心生喜欢。
MinIO的特点请查看官网,https://min.io/。
1、MinIO安装
进入官网下载对应的版本,可以选择linux、windows、docker等,本次选择windows环境
在这里插入图片描述
在这里插入图片描述
windows环境minio安装启动
查看minio版本

minio.exe -version
  • 1

在这里插入图片描述
首先进入minio.exe所在目录,在cmd命令行中输入如下命令即完成安装启动,其中server后面的地址是文件上传的存储目录。

minio.exe server D:\minio
  • 1

在这里插入图片描述
api端口是9000,所以下面的yml文件中端口需要配置为9000,accessKey和secretKey需要配置为启动窗口上对应的值。
启动成功后,访问默认地址http://127.0.0.1:9000/minio进入到minio控制台,输入账号密码登录即可。
在这里插入图片描述
在这里插入图片描述
可以在控制台创建bucketName,也可以在代码中创建。注意在启动服务后使用minio。

linux环境minio安装启动
创建data目录
mkdir/usr/local/minio/data
添加可执行权限
chmod +x minio
设置登录的access_key
export MINIO_ACCESS_KEY=minioadmin
设置登录的secret key
export MINIO_SECRET_KEY=minioadmin
启动 minio
./minio server /usr/local/minio/data
或指定端口号
./minio server /usr/local/minio/data --address=0.0.0.0:9001
其他同windows环境。
2、springboot集成MinIO
创建springboot工程,引入web依赖、minio依赖

<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.2.1</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

配置application.yml文件

spring:
  servlet:
    multipart:
      max-file-size: 200MB
      max-request-size: 200MB

minio:
  endpoint: http://localhost:9000
  accessKey: minioadmin
  secretKey: minioadmin
  nginxUrl: http://localhost:9000


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

创建Properties类接收上面四个属性

@ConfigurationProperties(prefix = "minio")
public class MinioProperties {
    /**
     * 连接地址
     */
    private String endpoint;
    /**
     * 用户名
     */
    private String accessKey;
    /**
     * 密码
     */
    private String secretKey;
    /**
     * 域名
     */
    private String nginxUrl;

    public String getEndpoint() {
        return endpoint;
    }

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

    public String getAccessKey() {
        return accessKey;
    }

    public void setAccessKey(String accessKey) {
        this.accessKey = accessKey;
    }

    public String getSecretKey() {
        return secretKey;
    }

    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }

    public String getNginxUrl() {
        return nginxUrl;
    }

    public void setNginxUrl(String nginxUrl) {
        this.nginxUrl = nginxUrl;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

创建配置类,注入MinIOClient

@Configuration
@EnableConfigurationProperties(MinioProperties.class)
public class MinioConfig {

    @Autowired
    private MinioProperties minioProperties;

    /**
     * 获取MinioClient
     */
    @Bean
    public MinioClient minioClient() {
        return MinioClient
                .builder()
                .endpoint(minioProperties.getEndpoint())
                .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
                .build();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

创建Client工具类,方便操作文件

@Component
public class MinioUtil {

    @Autowired
    private MinioProperties minioProperties;

    @Autowired
    private MinioClient minioClient;

    /**
     * 创建bucket
     */
    public void createBucket(String bucketName) throws Exception {
        if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * 删除bucket
     */
    public void removeBucket(String bucketName) throws Exception {
        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
    }

    /**
     * 获取全部bucket
     */
    public List<Bucket> getBuckets() throws Exception {
        return minioClient.listBuckets();
    }

    /**
     * 根据bucketName获取bucket
     * @param bucketName bucket名称
     */
    public Optional<Bucket> getBucket(String bucketName) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidResponseException, InternalException, ErrorResponseException, ServerException, XmlParserException, ServerException {
        return minioClient.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
    }

    /**
     * 上传文件
     */
    public MinioObject uploadFile(MultipartFile file, String bucketName) throws Exception {
        //判断文件是否为空,为空则返回
        if (null == file || 0 == file.getSize()) {
            return null;
        }
        //判断存储桶是否存在,不存在则创建
        createBucket(bucketName);
        //文件名
        String originalFilename = file.getOriginalFilename();
        //新的文件名 = 存储桶文件名_时间戳.后缀名
        assert originalFilename != null;
        String fileName = bucketName + "_" +
                new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + "_" +
                new Random().nextInt(1000) +
                originalFilename.substring(originalFilename.lastIndexOf("."));
        //开始上传
        minioClient.putObject(
                PutObjectArgs
                        .builder()
                        .bucket(bucketName)
                        .object(fileName)
                        .stream(file.getInputStream(), file.getSize(), -1)
                        .contentType(file.getContentType())
                        .build());
        String url = minioProperties.getEndpoint() + "/" + bucketName + "/" + fileName;
        String urlHost = minioProperties.getNginxUrl() + "/" + bucketName + "/" + fileName;
        return new MinioObject(url, urlHost);
    }

    /**
     * 下载文件
     */
    public void downloadFile(String filename, String bucketName, HttpServletResponse httpServletResponse){
        GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName).object(filename).build();
        try (GetObjectResponse response = minioClient.getObject(objectArgs)){
            byte[] buf = new byte[1024];
            int len;
            try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()){
                while ((len=response.read(buf))!=-1){
                    os.write(buf,0,len);
                }
                os.flush();
                byte[] bytes = os.toByteArray();
                httpServletResponse.setCharacterEncoding("utf-8");
                // 设置强制下载不打开
                httpServletResponse.setContentType("application/force-download");
                httpServletResponse.addHeader("Content-Disposition", "attachment;fileName=" + filename);
                try ( ServletOutputStream stream = httpServletResponse.getOutputStream()){
                    stream.write(bytes);
                    stream.flush();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 下载文件
     */
    public void downloadObject(String fileName, String bucketName, HttpServletResponse httpServletResponse) {
        try {
            GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName).object(fileName).build();
            InputStream file = minioClient.getObject(objectArgs);
            String filename = new String(fileName.getBytes("ISO8859-1"), "utf-8");
            httpServletResponse.setHeader("Content-Disposition", "attachment;filename=" + filename);
            ServletOutputStream servletOutputStream = httpServletResponse.getOutputStream();
            int len;
            byte[] buffer = new byte[1024];
            while ((len = file.read(buffer)) > 0) {
                servletOutputStream.write(buffer, 0, len);
            }
            servletOutputStream.flush();
            file.close();
            servletOutputStream.close();
        } catch (ErrorResponseException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 上传⽂件
     *
     * @param bucketName bucket名称
     * @param objectName ⽂件名称
     * @param stream     ⽂件流
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
     */
    public void putObject(String bucketName, String objectName, InputStream stream) throws Exception {
        minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, stream.available(), -1).contentType(objectName.substring(objectName.lastIndexOf("."))).build());
    }

    /**
     * 上传⽂件
     *
     * @param bucketName  bucket名称
     * @param objectName  ⽂件名称
     * @param stream      ⽂件流
     * @param size        ⼤⼩
     * @param contextType 类型
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
     */
    public void putObject(String bucketName, String objectName, InputStream stream, long size, String contextType) throws Exception {
        minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, size, -1).contentType(contextType).build());
    }

    /**
     * 删除⽂件
     *
     * @param bucketName bucket名称
     * @param objectName ⽂件名称
     * @throws Exception https://docs.minio.io/cn/java-client-apireference.html#removeObject
     */
    public void removeObject(String bucketName, String objectName) throws Exception {
        minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
    }

    /**
     * 获取⽂件url
     *
     * @param bucketName bucket名称
     * @param objectName ⽂件名称
     * @param expires    过期时间 <=7
     * @return url
     */
    public String getObjectURL(String bucketName, String objectName, Integer expires) throws Exception {
        return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(objectName).expiry(expires).build());
    }

    /**
     * 获取⽂件输入流
     *
     * @param bucketName bucket名称
     * @param objectName ⽂件名称
     * @return ⼆进制流
     */
    public InputStream getObject(String bucketName, String objectName) throws Exception {
        return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
    }

    /**
     * 获取⽂件信息
     *
     * @param bucketName bucket名称
     * @param objectName ⽂件名称
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject
     */
    public StatObjectResponse getObjectInfo(String bucketName, String objectName) throws Exception {
        return minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
    }

    /**
     * 查看文件对象列表
     *
     * @param bucketName 存储bucket名称
     * @return 存储bucket内文件对象信息
     */
    public List<MinioObject> listObjects(String bucketName) {
        Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).build());
        List<MinioObject> objectItems = new ArrayList<>();
        try {
            for (Result<Item> result : results) {
                Item item = result.get();
                MinioObject minioObject = new MinioObject();
                minioObject.setMinIoUrl(item.objectName());;
                minioObject.setSize(item.size());
                objectItems.add(minioObject);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return objectItems;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221

访问接口

	@PostMapping("/upload")
    public String fileUpload(MultipartFile file) throws Exception {
        MinioObject minioObject = minioUtil.uploadFile(file, "public");
        System.out.println("bucket01.getMinIoUrl() = " + minioObject.getMinIoUrl());
        System.out.println("bucket01.getNginxUrl() = " + minioObject.getNginxUrl());
        return minioObject.getMinIoUrl();
    }
	@GetMapping("download")
    public Object download(HttpServletResponse response) throws Exception {
        minioUtil.downloadObject("","image",response);
        return "success";
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

文件上传完成之后如图
在这里插入图片描述
注意:可以通过可视化界面设置存储桶的权限级别,是否开发,访问的url有效期等,具体看组件提供的方法,如

getObjectURL()获取桶内文件的url地址,如果设置了只写权限,用户直接访问地址是查看不了的;
getObgect()可以获取桶内对应文件的流对象,进行文件流传输;
presignedGetObject()返回的是进行加密算法的地址,通过它可以直接访问文件;
getPresignedObjectUrl(Method.GET,"asiatrip","minio.png",10,null)有效期10秒,可以通过get方式访问;
makeBucket 创建桶
listBuckets 列出当前所有桶
bucketExists 判断桶是否存在
removeBucket 移除桶
listObjects 获取桶内的内容
listIncompleteUploads 获取上传中断的内容,支持断点续传
getObject 下载文件
putObject 上传文件
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

文件存储可以使用之后也可以通过配置nginx的方式对静态资源进行代理,前端直接通过url进行访问。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/110942
推荐阅读
相关标签
  

闽ICP备14008679号