Home >Java >javaTutorial >How SpringBoot uses Minio for file storage
MinIO
is a high-performance object storage solution that natively supports Kubernetes
deployment. MinIO
provides an Amazon Web Services S3
that is API
compatible and supports all core S3
functionality.
MinIO
Object storage uses buckets
to organize objects. Buckets are similar to folders or directories in a file system, where each bucket can hold any number of objects. MinIO
buckets provide the same functionality as AWS S3
buckets.
The advantages of MinIO
are:
High performance:
MinIO
is the world’s leading Pioneer in object storage, with read/write speeds of up to 183 GB/second
and 171 GB/second
on standard hardware.
Scalability:
MinIO
leverages the hard-won knowledge of web
scalers to provide the best solution for object storage Bringing a simple storage scaling model, in MinIO
, scaling starts from a single cluster that can be federated with other MinIO
clusters to create a global namespace, and can be spanned when needed Multiple different data centers. The namespace can be expanded by adding more clusters, more racks, until the goal is achieved.
Cloud native support:
MinIO
is a software built from scratch in the past 4 years and is in line with all native clouds Computing architecture and construction process, and includes the latest cloud computing new technologies and concepts. This includes container technology that supports Kubernetes
, microservices and multi-tenancy. Make object storage more friendly to Kubernetes
.
Open source code and enterprise-level support:
MinIO
Based on Apache V2 license 100%
open source code. This means that customers of MinIO
can automatically, unrestrictedly and freely use and integrate MinIO
, freely innovate and create, freely modify, and freely re-release new ones. Version and software. Indeed, MinIO
has strongly supported and driven many Fortune 500 companies. In addition, the diversity and professionalism of its deployment provide advantages that other software cannot match.
Please make sure the installation is complete before starting the experimentminio
:
SpringBoot project and introduce
minio dependencies in
pom:
<dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.2.1</version> </dependency>In the configuration file, declare
Information about minio:
minio: url: http://192.168.40.169:9000 # minio配置的地址,端口9000,注意不是控制台的端口 accessKey: minioadmin # 账号 secretKey: minioadmin # 密码 bucketName: test-bucket # MinIO桶名字Create a configuration class below to create
MinioClient:
@Data @Configuration @ConfigurationProperties(prefix = "minio") public class MinioConfig { /** * 服务地址 */ private String url; /** * 用户名 */ private String accessKey; /** * 密码 */ private String secretKey; /** * 存储桶名称 */ private String bucketName; @Bean public MinioClient getMinioClient() throws Exception { MinioClient minioClient = MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build(); //判断桶是否存在,不存在则新建 if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())){ minioClient.makeBucket(MakeBucketArgs.builder() .bucket(bucketName) .build()); } return minioClient; } }Create a tool class below
MinioTool Encapsulate commonly used operations in tool classes:
@Component public class MinioTool { @Autowired private MinioClient minioClient; @Autowired private MinioConfig minioConfig; /** * 查看存储bucket是否存在 * * @param bucketName 存储bucket * @return boolean */ public Boolean bucketExists(String bucketName) { Boolean found; try { found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); } catch (Exception e) { e.printStackTrace(); return false; } return found; } /** * 创建存储bucket * * @param bucketName 存储bucket名称 * @return Boolean */ public Boolean makeBucket(String bucketName) { try { minioClient.makeBucket(MakeBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 删除存储bucket * * @param bucketName 存储bucket名称 * @return Boolean */ public Boolean removeBucket(String bucketName) { try { minioClient.removeBucket(RemoveBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 查看文件对象 * * @param bucketName 存储bucket名称 * @return 存储bucket内文件对象信息 */ public Iterable<Result<Item>> listObjects(String bucketName) { Iterable<Result<Item>> results = minioClient.listObjects( ListObjectsArgs.builder().bucket(bucketName).build()); return results; } /** * 批量删除文件对象 * * @param bucketName 存储bucket名称 * @param objects 对象名称集合 */ public Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> objects) { List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList()); Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build()); return results; } /** * 文件上传 * 文件名称相同会覆盖 * @param file 文件 * @return Boolean */ public Boolean upload(MultipartFile file, String fileName) { try { if (!bucketExists(minioConfig.getBucketName())) { makeBucket(minioConfig.getBucketName()); } PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(minioConfig.getBucketName()).object(fileName) .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build(); minioClient.putObject(objectArgs); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 文件下载 * * @param fileName 文件名称 * @param res response * @return Boolean */ public void download(String fileName, HttpServletResponse res) { GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(minioConfig.getBucketName()) .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(); res.setCharacterEncoding("utf-8"); //设置强制下载不打开 res.setContentType("application/force-download"); res.addHeader("Content-Disposition", "attachment;fileName=" + fileName); try (ServletOutputStream stream = res.getOutputStream()) { stream.write(bytes); stream.flush(); } } } catch (Exception e) { e.printStackTrace(); } } public String getFileUrl(String fileName){ return StringFormatter.concat(minioConfig.getUrl(), "/", minioConfig.getBucketName(), "/", fileName).getValue(); } }Write test interfaces and test:
@Component public class MinioTool { @Autowired private MinioClient minioClient; @Autowired private MinioConfig minioConfig; /** * 查看存储bucket是否存在 * * @param bucketName 存储bucket * @return boolean */ public Boolean bucketExists(String bucketName) { Boolean found; try { found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); } catch (Exception e) { e.printStackTrace(); return false; } return found; } /** * 创建存储bucket * * @param bucketName 存储bucket名称 * @return Boolean */ public Boolean makeBucket(String bucketName) { try { minioClient.makeBucket(MakeBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 删除存储bucket * * @param bucketName 存储bucket名称 * @return Boolean */ public Boolean removeBucket(String bucketName) { try { minioClient.removeBucket(RemoveBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 查看文件对象 * * @param bucketName 存储bucket名称 * @return 存储bucket内文件对象信息 */ public Iterable<Result<Item>> listObjects(String bucketName) { Iterable<Result<Item>> results = minioClient.listObjects( ListObjectsArgs.builder().bucket(bucketName).build()); return results; } /** * 批量删除文件对象 * * @param bucketName 存储bucket名称 * @param objects 对象名称集合 */ public Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> objects) { List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList()); Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build()); return results; } /** * 文件上传 * 文件名称相同会覆盖 * @param file 文件 * @return Boolean */ public Boolean upload(MultipartFile file, String fileName) { try { if (!bucketExists(minioConfig.getBucketName())) { makeBucket(minioConfig.getBucketName()); } PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(minioConfig.getBucketName()).object(fileName) .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build(); minioClient.putObject(objectArgs); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 文件下载 * * @param fileName 文件名称 * @param res response * @return Boolean */ public void download(String fileName, HttpServletResponse res) { GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(minioConfig.getBucketName()) .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(); res.setCharacterEncoding("utf-8"); //设置强制下载不打开 res.setContentType("application/force-download"); res.addHeader("Content-Disposition", "attachment;fileName=" + fileName); try (ServletOutputStream stream = res.getOutputStream()) { stream.write(bytes); stream.flush(); } } } catch (Exception e) { e.printStackTrace(); } } public String getFileUrl(String fileName){ return StringFormatter.concat(minioConfig.getUrl(), "/", minioConfig.getBucketName(), "/", fileName).getValue(); } }3. TestTest upload files: If you use the returned url to directly access the file, you can find that the return permission is insufficient: You need to change it here
Bucket The
Access Policy defaults to
private and can be modified to
public without authentication, but security cannot be guaranteed:
private, you can download through
MinioClient, use the
download test interface to download the file:
http://localhost:8080/file/download/20cab4e3979eba6003f95aca0dc75c63 .jpg
The above is the detailed content of How SpringBoot uses Minio for file storage. For more information, please follow other related articles on the PHP Chinese website!