Comment SpringBoot utilise Minio pour le stockage de fichiers
1. minio
MinIO
est une solution de stockage d'objets hautes performances qui prend en charge nativement le déploiement Kubernetes
. MinIO
fournit une API
compatible avec Amazon Web Services S3
et prend en charge toutes les fonctionnalités de base S3
. MinIO
是一个高性能的对象存储原生支持 Kubernetes
部署的解决方案。 MinIO
提供了一个 Amazon Web Services S3
兼容 API
并支持所有核心 S3
功能。
MinIO
对象存储使用 buckets
来组织对象。 存储桶类似于文件系统中的文件夹或目录,其中每个 桶可以容纳任意数量的对象。 MinIO
存储桶提供 与 AWS S3
存储桶相同的功能。
其中 MinIO
的优势有:
高性能:
MinIO
是全球领先的对象存储先锋,在标准硬件上,读/写速度上高达183 GB / 秒
和 171 GB / 秒
。
可扩展性:
MinIO
利用了web
缩放器的来之不易的知识,为对象存储带来了简单的存储缩放模型, 在 MinIO
, 扩展从单个群集开始,该群集可以与其他MinIO
群集联合以创建全局名称空间, 并在需要时可以跨越多个不同的数据中心。 通过添加更多集群可以扩展名称空间, 更多机架,直到实现目标。
云原生支持:
MinIO
是在过去4年的时间内从0开始打造的一款软件 ,符合一切原生云计算的架构和构建过程,并且包含最新的云计算的全新的技术和概念。 其中包括支持Kubernetes
、微服和多租户的的容器技术。使对象存储对于 Kubernetes
更加友好。
源码开放与企业级支持:
MinIO
基于Apache V2 license 100%
开放源代码 。 这就意味着 MinIO
的客户能够自动的、无限制、自由免费使用和集成MinIO
、自由的创新和创造、 自由的去修改、自由的再次发行新的版本和软件. 确实, MinIO
强有力的支持和驱动了很多世界500强的企业。 此外,其部署的多样性和专业性提供了其他软件无法比拟的优势。
在实验开始前请确保安装完成了 minio
:
二、SpringBoot 使用 Minio 进行文件存储
首先新建一个 SpringBoot
项目,在 pom
中引入 minio
依赖:
<dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.2.1</version> </dependency>
在配置文件中,声明出 minio
的信息:
minio: url: http://192.168.40.169:9000 # minio配置的地址,端口9000,注意不是控制台的端口 accessKey: minioadmin # 账号 secretKey: minioadmin # 密码 bucketName: test-bucket # MinIO桶名字
下面创建一个配置类,对 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; } }
下面创建一个工具类 MinioTool
将常用的操作封装在工具类中:
@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(); } }
编写测试接口,进行测试:
@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(); } }
三、测试
测试上传文件:
如果使用 返回的 url 直接访问文件,可以发现返回权限不足:
这里需要改一下 Bucket
的 Access Policy
,默认为 private
,可以修改为 public
便无需认证,但安全性无法保证:
再次进行访问,文件就可以打开了:
如果需要保持 private
,可以通过 MinioClient
进行下载,使用 download
测试接口下载文件:http://localhost:8080/file/download/20cab4e3979eba6003f95aca0dc75c63.jpg
MinIO
utilise des buckets
pour organiser les objets. Les compartiments sont similaires aux dossiers ou répertoires d'un système de fichiers, où chaque compartiment peut contenir n'importe quel nombre d'objets. Le compartiment MinIO
fournit les mêmes fonctionnalités que le compartiment AWS S3
. Les avantages de
MinIO
sont :
MinIO
est le premier pionnier mondial du stockage d'objets sur du matériel standard, Read. /write à des vitesses allant jusqu'à 183 Go/sec
et 171 Go/sec
. 🎜🎜Évolutivité :🎜🎜MinIO
exploite les connaissances durement acquises des scalers web
pour simplifier le stockage objet. Modèle de mise à l'échelle du stockage, dans MinIO
, la mise à l'échelle commence à partir d'un seul cluster, qui peut être fédéré avec d'autres clusters MinIO
pour créer un espace de noms global, et peut s'étendre sur plusieurs clusters différents si nécessaire pour les centres de données. L'espace de noms peut être étendu en ajoutant plus de clusters, plus de racks, jusqu'à ce que l'objectif soit atteint. 🎜🎜Support natif du cloud :🎜🎜MinIO
est un logiciel construit à partir de zéro au cours des 4 dernières années, conforme à l'architecture et au processus de construction de tout le cloud computing natif, et contient les dernières nouvelles technologies et concepts de cloud computing. Cela inclut la technologie de conteneur qui prend en charge Kubernetes
, les microservices et la multilocation. Rendre le stockage d'objets plus convivial pour Kubernetes
. 🎜🎜Support Open source et niveau entreprise :🎜🎜MinIO
est basé sur la Licence Apache V2 100%
open source. Cela signifie que les clients de MinIO
peuvent automatiquement, sans restriction et librement utiliser et intégrer MinIO
, innover et créer librement, modifier librement et redistribuer librement de nouvelles versions et logiciels. MinIO
a fortement soutenu et dirigé de nombreuses entreprises Fortune 500. De plus, la diversité et le professionnalisme de son déploiement offrent des avantages que d’autres logiciels ne peuvent égaler. 🎜🎜Veuillez vous assurer que l'installation de minio
est terminée avant de commencer l'expérience : 🎜🎜
SpringBoot
et introduisez-le dans pom
minio
dépend de : 🎜rrreee🎜Dans le fichier de configuration, déclarez les informations de minio
: 🎜rrreee🎜Créez une classe de configuration ci-dessous pour effectuer MinioClient
Créer : 🎜rrreee🎜 Créez une classe d'outils MinioTool
ci-dessous et encapsulez les opérations courantes dans la classe d'outils : 🎜rrreee🎜Écrivez une interface de test et testez-la : 🎜rrreee🎜 3. Testez 🎜 🎜Test de fichiers de téléchargement : 🎜🎜

Politique d'accès
de Bucket
. La valeur par défaut est private, qui peut être modifié en public code> Aucune authentification n'est requise, mais la sécurité ne peut être garantie : 🎜🎜<img src="https://img.php.cn/upload%20/article/000/887/227/168377857086128.jpg" alt="Comment utiliser Minio avec le stockage de fichiers SpringBoot">🎜🎜<img src="https://img.php.cn/upload/article/000/%20887/227/168377857019765.jpg" alt="Comment SpringBoot utilise Minio pour le stockage de fichiers"> 🎜🎜<img src="https://img.php.cn/upload/article/000/887/227/168377857057222%20.jpg" alt="Comment SpringBoot utilise Minio pour le stockage de fichiers">🎜🎜Visitez à nouveau, le fichier peut être ouvert : 🎜🎜<img src="https://img.php.cn/upload/article/000/%20887/227/168377857057448.jpg" alt="Comment SpringBoot utilise-t-il Minio pour le stockage de fichiers"> 🎜🎜Si vous devez garder <code>privé
, vous pouvez télécharger via MinioClient
et utilisez l'interface de test download
pour télécharger le fichier : http://localhost: 8080/file/download/20cab4e3979eba6003f95aca0dc75c63.jpg
🎜🎜🎜🎜Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undress AI Tool
Images de déshabillage gratuites

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Introduction à Jasypt Jasypt est une bibliothèque Java qui permet à un développeur d'ajouter des fonctionnalités de chiffrement de base à son projet avec un minimum d'effort et ne nécessite pas une compréhension approfondie du fonctionnement du chiffrement. Haute sécurité pour le chiffrement unidirectionnel et bidirectionnel. technologie de cryptage basée sur des normes. Cryptez les mots de passe, le texte, les chiffres, les binaires... Convient pour l'intégration dans des applications basées sur Spring, API ouverte, pour une utilisation avec n'importe quel fournisseur JCE... Ajoutez la dépendance suivante : com.github.ulisesbocchiojasypt-spring-boot-starter2 1.1. Les avantages de Jasypt protègent la sécurité de notre système. Même en cas de fuite du code, la source de données peut être garantie.

1. Redis implémente le principe du verrouillage distribué et pourquoi les verrous distribués sont nécessaires. Avant de parler de verrous distribués, il est nécessaire d'expliquer pourquoi les verrous distribués sont nécessaires. Le contraire des verrous distribués est le verrouillage autonome. Lorsque nous écrivons des programmes multithreads, nous évitons les problèmes de données causés par l'utilisation d'une variable partagée en même temps. Nous utilisons généralement un verrou pour exclure mutuellement les variables partagées afin de garantir l'exactitude de celles-ci. les variables partagées. Son champ d’utilisation est dans le même processus. S’il existe plusieurs processus qui doivent exploiter une ressource partagée en même temps, comment peuvent-ils s’exclure mutuellement ? Les applications métier d'aujourd'hui sont généralement une architecture de microservices, ce qui signifie également qu'une application déploiera plusieurs processus si plusieurs processus doivent modifier la même ligne d'enregistrements dans MySQL, afin d'éviter les données sales causées par des opérations dans le désordre, les besoins de distribution. à introduire à ce moment-là. Le style est verrouillé. Vous voulez marquer des points

1. Personnalisez RedisTemplate1.1, mécanisme de sérialisation par défaut RedisAPI. L'implémentation du cache Redis basée sur l'API utilise le modèle RedisTemplate pour les opérations de mise en cache des données. Ici, ouvrez la classe RedisTemplate et affichez les informations sur le code source de la classe. Déclarer la clé, diverses méthodes de sérialisation de la valeur, la valeur initiale est vide @NullableprivateRedisSe

Springboot lit le fichier, mais ne peut pas accéder au dernier développement après l'avoir empaqueté dans un package jar. Il existe une situation dans laquelle Springboot ne peut pas lire le fichier après l'avoir empaqueté dans un package jar. La raison en est qu'après l'empaquetage, le chemin virtuel du fichier. n’est pas valide et n’est accessible que via le flux Read. Le fichier se trouve sous les ressources publicvoidtest(){Listnames=newArrayList();InputStreamReaderread=null;try{ClassPathResourceresource=newClassPathResource("name.txt");Input

1. @Import introduit les classes ordinaires @Import introduit les classes ordinaires peut nous aider à définir les classes ordinaires comme des Beans. @Import peut être ajouté aux classes correspondant à @SpringBootApplication (classe de démarrage), @Configuration (classe de configuration) et @Component (classe de composant). Remarque : @RestController, @Service et @Repository appartiennent tous à @Component@SpringBootApplication@Import(ImportBean.class)//ImportBean via l'annotation @Import.

Lorsque Springboot+Mybatis-plus n'utilise pas d'instructions SQL pour effectuer des opérations d'ajout de plusieurs tables, les problèmes que j'ai rencontrés sont décomposés en simulant la réflexion dans l'environnement de test : Créez un objet BrandDTO avec des paramètres pour simuler le passage des paramètres en arrière-plan. qu'il est extrêmement difficile d'effectuer des opérations multi-tables dans Mybatis-plus. Si vous n'utilisez pas d'outils tels que Mybatis-plus-join, vous pouvez uniquement configurer le fichier Mapper.xml correspondant et configurer le ResultMap malodorant et long, puis. écrivez l'instruction SQL correspondante Bien que cette méthode semble lourde, elle est très flexible et nous permet de

Scénario d'utilisation 1. La commande a été passée avec succès mais le paiement n'a pas été effectué dans les 30 minutes. Le paiement a expiré et la commande a été automatiquement annulée 2. La commande a été signée et aucune évaluation n'a été effectuée pendant 7 jours après la signature. Si la commande expire et n'est pas évaluée, le système donne par défaut une note positive. 3. La commande est passée avec succès. Si le commerçant ne reçoit pas la commande pendant 5 minutes, la commande est annulée. 4. Le délai de livraison expire et. un rappel par SMS est envoyé... Pour les scénarios avec des délais longs et de faibles performances en temps réel, nous pouvons utiliser la planification des tâches pour effectuer un traitement d'interrogation régulier. Par exemple : xxl-job Aujourd'hui, nous allons choisir

SpringBoot et SpringMVC sont tous deux des frameworks couramment utilisés dans le développement Java, mais il existe des différences évidentes entre eux. Cet article explorera les fonctionnalités et les utilisations de ces deux frameworks et comparera leurs différences. Tout d’abord, découvrons SpringBoot. SpringBoot a été développé par l'équipe Pivotal pour simplifier la création et le déploiement d'applications basées sur le framework Spring. Il fournit un moyen rapide et léger de créer des fichiers exécutables autonomes.
