Win10安装Minio及SpringBoot集成Minio

简介

Minio是一款开源的云存储服务器,旨在为企业和个人用户提供简单、易用、高性能的对象存储服务。与传统的云存储产品不同,Minio是构建在HTTP服务之上的对象存储服务器,它支持AWS S3 API,可以为用户提供简单易用的对象存储服务,可用于存储各种类型的文件,包括图片、音频、视频等。

一、下载

我们需要先到minio官网进行下载:下载地址

二、运行启动minio

下载完成后,由于minio.exe是不能直接执行的,需要cmd进入下载目录执行命令:

minio.exe server D:\data

出现以上界面说明启动成功,打开浏览器访问:http://localhost:9000,就可以看到minio自带的管理后台了,登录的用户名和密码都是minioadmin

三、将minio集成到windows服务中

由于每次都需要打开cmd窗口运行命令后才能访问minio,关掉就不能访问了,非常不方便,所以我们可以将minio集成到服务中,这样就不用每次都用cmd启动了。

集成minio到服务需要下载WinSW.exe,下载地址

下载完成后将WinSW.exe和nimio.exe放到一个自定义的目录下,可以将WinSW.exe重命名成一个喜欢的名字,比如:minio-server.exe

在目录下新建一个minio-server.xml文件,内容如下:

<service>
    <id>minio-server</id>
    <name>minio-server</name>
    <description>minio文件存储服务器</description>
    <!-- 可设置环境变量 -->
    <env name="MINIO_HOME" value="%BASE%"/>
    <executable>%BASE%\minio.exe</executable>
    <arguments>server "%BASE%\data"</arguments>
    <logpath>%BASE%\logs</logpath>
    <log mode="roll-by-size-time">
      <sizeThreshold>10240</sizeThreshold>
      <pattern>yyyyMMdd</pattern>
      <autoRollAtTime>00:00:00</autoRollAtTime>
      <zipOlderThanNumDays>5</zipOlderThanNumDays>
      <zipDateFormat>yyyyMMdd</zipDateFormat>
    </log>
</service>

需在环境变量中新建MINIO_HOME,值就是存放minio.exe的目录

打开cmd进入到目录下,运行命令安装minio服务:

minio-server.exe install

如果想卸载minio-server,运行:

minio-server.exe uninstall

访问http://localhost:9000,出现minio的管理后台,说明服务安装成功

四、Spring Boot集成Minio

1.首先引入依赖
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.4.3</version>
</dependency>
2.在yml文件中添加配置
minio:
  url: http://localhost:9000
  access-key: minioadmin
  secret-key: minioadmin
  bucket: test
3.添加minio配置类
@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {

    private String accessKey;

    private String secretKey;

    private String url;

    @Bean
    public MinioClient minioClient() {
        try {
            return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
        }catch (Exception e) {
            throw new RuntimeException("初始化MinioClient失败", e);
        }
    }

}
4.编写工具类
@Component
public class MinioUtils {

    @Resource
    private MinioClient minioClient;

    @Value("${minio.bucket}")
    private String bucketName;

    /**
     * 判断存储桶是否存在
     *
     * @return 桶是否存在
     */
    public boolean bucketExists() {
        try {
            return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            throw new RuntimeException("桶不存在", e);
        }
    }

    /**
     * 创建桶
     */
    public void makeBucket() {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            throw new RuntimeException("创建桶失败", e);
        }
    }

    /**
     * 上传单个对象
     *
     * @param file 文件
     * @return 上传成功
     */
    public SysResult putObject(MultipartFile file) {
        if (file == null || file.isEmpty())
            throw new IllegalArgumentException("文件不能为空");

        try (InputStream inputStream = file.getInputStream()){
            //检查存储桶是否存在
            if (!bucketExists())
                makeBucket();

            // 获取文件名
            String fileName = file.getOriginalFilename();
            
            assert fileName != null;
            // 生成随机的对象名称
            String objectName = IdUtils.simpleUUID() + "." + FileUtil.getFileSuffix(fileName);

            // 添加自定义的元数据
            Map<String, String> meta = new HashMap<>();
            meta.put("file-name", fileName);

            // 添加对象
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .userMetadata(meta)
                    .stream(inputStream, file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build());
            return SysResult.success("上传成功", objectName);
        } catch (Exception e) {
            throw new RuntimeException("上传失败", e);
        }
    }

    /**
     * 上传多个对象
     *
     * @param files 文件数组
     * @return 上传成功
     */
    public SysResult putObject(MultipartFile[] files) {
        for (MultipartFile file : files) {
            putObject(file);
        }
        return SysResult.success("上传成功");
    }

    /**
     * 删除一个对象
     *
     * @param objectName 对象名称
     * @return 是否删除成功
     */
    public boolean removeObject(String objectName) {
        if (bucketExists()) {
            try {
                minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
                return true;
            } catch (Exception e) {
                throw new RuntimeException("删除失败", e);
            }
        }
        return false;
    }


    /**
     * 删除多个对象,返回删除失败的对象列表
     *
     * @param objectNames 对象List
     * @return 删除失败的对象List
     */
    public List<String> removeObjects(List<String> objectNames) {
        List<String> deleteErrorNames = new ArrayList<>();
        if (bucketExists()) {
            for (String objectName : objectNames) {
                if (!removeObject(objectName)) {
                    deleteErrorNames.add(objectName);
                }
            }
        }
        return deleteErrorNames;
    }

    /**
     * 获取对象的元数据
     *
     * @param objectName 对象名称
     * @return 元数据
     */
    public SysResult statObject(String objectName) {
        try {
            if (bucketExists()) {
                StatObjectResponse response = minioClient.statObject(StatObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build());
                // 输出对象的元数据信息
                Map<String, String> metadata = response.userMetadata();
                // 返回
                return SysResult.data(metadata);
            }
        } catch (Exception e) {
            throw new RuntimeException("获取元数据失败", e);
        }
        return null;
    }

    /**
     * 获取文件的临时访问路径
     *
     * @param objectName 对象名称
     * @return 临时访问url
     */
    public String getObjectUrl(String objectName) {
        String url = "";
        try {
            if (bucketExists()) {
                // 设置预签名URL的有效期(以秒为单位)
                int expiresInSeconds = 3600; // 一小时
                url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                        .method(Method.GET) //只能get请求访问
                        .bucket(bucketName)
                        .object(objectName)
                        .expiry(expiresInSeconds) // 设置有效时间
                        .build());
            }
        } catch (Exception e) {
            throw new RuntimeException("获取失败", e);
        }
        return url;
    }


    /**
     * 获取(下载)单个文件
     *
     * @param fileName 文件名
     * @return 输出流
     */
    public ResponseEntity<ByteArrayResource> getObject(String fileName){
        // 获取输入流
        try (InputStream inputStream = minioClient.getObject(GetObjectArgs.builder()
                .bucket(bucketName)
                .object(fileName).build())) {

            byte[] byteArray = IOUtils.toByteArray(inputStream);
            ByteArrayResource resource = new ByteArrayResource(byteArray);

            //设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName);

            //开始下载
            return ResponseEntity.ok()
                    .headers(headers)
                    .contentLength(byteArray.length)
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .body(resource);
        }catch (Exception e) {
            throw new RuntimeException("下载失败", e);
        }
    }


    /**
     * 获取(下载)多个文件,写进zip压缩包返回
     *
     * @param objectNames 资源名数组
     * @return 输出流
     */
    public ResponseEntity<byte[]> getObjectList(String[] objectNames) {
        // 创建一个输出流,将文件写入压缩包
        try (ByteArrayOutputStream aos = new ByteArrayOutputStream();
             ZipOutputStream zos = new ZipOutputStream(aos)) {

            for (String objectName : objectNames) {
                // 获取对象
                InputStream inputStream = minioClient.getObject(
                        GetObjectArgs.builder()
                                .bucket(bucketName)
                                .object(objectName)
                                .build());

                // 创建一个新的ZIP条目,并将文件写入压缩包
                ZipEntry zipEntry = new ZipEntry(objectName);
                zos.putNextEntry(zipEntry);

                byte[] buffer = new byte[8192];
                int length;
                while ((length = inputStream.read(buffer)) > 0) {
                    zos.write(buffer, 0, length);
                }

                // 关闭当前的ZIP条目
                zos.closeEntry();
                inputStream.close();
            }

            // 关闭 ZIP 输出流
            zos.close();

            // 将压缩包的字节数组作为响应体返回
            byte[] zipBytes = aos.toByteArray();

            //设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=output.zip");

            //开始下载
            return ResponseEntity.ok()
                    .headers(headers)
                    .contentLength(zipBytes.length)
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .body(zipBytes);
        } catch (Exception e) {
            throw new RuntimeException("文件下载失败", e);
        }
    }
}
5.编写控制器
@RestController
@RequestMapping(value = "/file")
public class FileController {

    @Resource
    private MinioUtils minioUtils;

    /**
     * 获取元数据
     * @param fileName 文件名
     * @return 元数据
     */
    @GetMapping(value = "/stat")
    public SysResult stat(String fileName) {
        return minioUtils.statObject(fileName);
    }

    /**
     * 根据文件名获取临时访问URL
     * @param fileName 文件名
     * @return 临时访问URL
     */
    @GetMapping(value = "/getUrl")
    public SysResult get(String fileName) {
        return SysResult.data(minioUtils.getObjectUrl(fileName));
    }

    /**
     * 下载单个文件
     *
     * @param fileName 文件名
     * @return 流
     */
    @GetMapping(value = "/download")
    public ResponseEntity<ByteArrayResource> downloadFile(String fileName) {
        return minioUtils.getObject(fileName);
    }

    /**
     * 下载多个文件到压缩包返回
     * @param fileName 要下载的文件名数组
     * @return 压缩流
     */
    @GetMapping(value = "/package")
    public ResponseEntity<byte[]> list(String[] fileName) {
        return minioUtils.getObjectList(fileName);
    }

    /**
     * 上传单个文件
     * @param file 文件
     * @return 是否上传成功
     */
    @PostMapping(value = "/upload")
    public SysResult upload(@RequestParam("file") MultipartFile file) {
        return minioUtils.putObject(file);
    }

    /**
     * 上传多个文件
     *
     * @param file 文件数组
     * @return 上传成功
     */
    @PostMapping(value = "/uploadList")
    public SysResult uploadList(@RequestParam("file") MultipartFile[] file) {
        return minioUtils.putObject(file);
    }

    /**
     * 删除单个文件
     *
     * @param fileName 文件名
     * @return 删除成功
     */
    @GetMapping(value = "/remove")
    public SysResult remove(String fileName) {
        minioUtils.removeObject(fileName);
        return SysResult.success("删除成功", fileName);
    }
}

接下来就可以跟接口愉快得玩耍了。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当将MinIOSpring Boot集成时,您可以使用MinIO Java客户端库来与MinIO对象存储系统进行交互。以下是一些步骤可以帮助您开始整合: 1. 首先,您需要在Spring Boot项目的依赖项中添加MinIO Java客户端库。在您的`pom.xml`文件中添加以下依赖项: ```xml <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.0.6</version> </dependency> ``` 2. 创建一个配置类来配置MinIO连接和操作。在您的Spring Boot项目中创建一个名为`MinioConfig`的类,并添加以下代码: ```java @Configuration public class MinioConfig { @Value("${minio.accessKey}") private String accessKey; @Value("${minio.secretKey}") private String secretKey; @Value("${minio.endpoint}") private String endpoint; @Bean public MinioClient minioClient() { return MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); } } ``` 在上面的代码中,我们使用`@Value`注解从配置文件中获取MinIO的访问密钥、秘钥和端点信息,并创建一个`MinioClient` bean。 3. 在需要使用MinIO的地方注入`MinioClient`并进行操作。例如,如果您想上传文件到MinIO,可以创建一个服务类并注入`MinioClient`,然后编写上传文件的方法: ```java @Service public class MinioService { private final MinioClient minioClient; public MinioService(MinioClient minioClient) { this.minioClient = minioClient; } public void uploadFile(String bucketName, String objectName, String filePath) { try { minioClient.uploadObject(UploadObjectArgs.builder() .bucket(bucketName) .object(objectName) .filename(filePath) .build()); System.out.println("File uploaded successfully"); } catch (Exception e) { e.printStackTrace(); } } } ``` 在上面的代码中,我们通过注入的`MinioClient`对象调用`uploadObject`方法来上传文件。 这只是一个简单的示例,您可以根据您的需求进一步扩展和使用MinIO的其他功能。 请确保在`application.properties`或`application.yml`配置文件中提供正确的MinIO连接信息,例如: ``` minio.accessKey=your_access_key minio.secretKey=your_secret_key minio.endpoint=http://localhost:9000 ``` 这是一个基本的MinIOSpring Boot集成示例。您可以根据您的具体需求和业务逻辑进行进一步的开发和调整。希望对您有所帮助!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值