MinIO中上传缩略图

需求:在读取minio的图片的时候,有的图片的大小很大,导致读取的速度就会很慢,对于客户的体验并不好。

解决办法:在用户上传图片的时候上传一份缩略图,读取图片的时候只读取缩略图,这样读取的速度就会增加。

代码:

0、配置文件

minio:endpoint: http://IP:9000      # MinIO服务地址fileHost: http://IP:9000      # 文件地址hostbucketName: pugapp                      # 存储桶bucket名称accessKey: root                         # 用户名secretKey: root123456789                     # 密码imgSize: 20                           # 图片大小限制,单位:mfileSize: 20                          # 文件大小限制,单位:m

1、新建MinIO配置类

@Configuration
@Data
public class MinIOConfig {@Value("${minio.endpoint}")private String endpoint;@Value("${minio.fileHost}")private String fileHost;@Value("${minio.bucketName}")private String bucketName;@Value("${minio.accessKey}")private String accessKey;@Value("${minio.secretKey}")private String secretKey;@Value("${minio.imgSize}")private Integer imgSize;@Value("${minio.fileSize}")private Integer fileSize;@Beanpublic MinIoUploadService creatMinioClient() {return new MinIoUploadService(endpoint, bucketName, accessKey, secretKey, imgSize, fileSize);}
}

2、新建MinIO工具类

/*** MinIO工具类*/
@Slf4j
public class MinIoUploadService {private MinioClient minioClient;private String endpoint;private String bucketName;private String accessKey;private String secretKey;private Integer imgSize;private Integer fileSize;private final String SEPARATOR = "/";public MinIoUploadService() {}public MinIoUploadService(String endpoint, String bucketName, String accessKey, String secretKey, Integer imgSize, Integer fileSize) {this.endpoint = endpoint;this.bucketName = bucketName;this.accessKey = accessKey;this.secretKey = secretKey;this.imgSize = imgSize;this.fileSize = fileSize;createMinioClient();}/*** 创建基于Java端的MinioClient*/public void createMinioClient() {try {if (null == minioClient) {log.info("开始创建 MinioClient...");minioClient = MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();createBucket(bucketName);log.info("创建完毕 MinioClient...");}} catch (Exception e) {log.error("MinIO服务器异常:{}", e);}}/*** 获取上传文件前缀路径** @return*/public String getBasisUrl() {return endpoint + SEPARATOR + bucketName + SEPARATOR;}/******************************  Operate Bucket Start  ******************************//*** 启动SpringBoot容器的时候初始化Bucket* 如果没有Bucket则创建** @throws Exception*/public void createBucket(String bucketName) throws Exception {if (!bucketExists(bucketName)) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());}}/*** 判断Bucket是否存在,true:存在,false:不存在** @return* @throws Exception*/public boolean bucketExists(String bucketName) throws Exception {return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());}/*** 获得Bucket的策略** @param bucketName* @return* @throws Exception*/public String getBucketPolicy(String bucketName) throws Exception {String bucketPolicy = minioClient.getBucketPolicy(GetBucketPolicyArgs.builder().bucket(bucketName).build());return bucketPolicy;}/*** 获得所有Bucket列表** @return* @throws Exception*/public List<Bucket> getAllBuckets() throws Exception {return minioClient.listBuckets();}/*** 根据bucketName获取其相关信息** @param bucketName* @return* @throws Exception*/public Optional<Bucket> getBucket(String bucketName) throws Exception {return getAllBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();}/*** 根据bucketName删除Bucket,true:删除成功; false:删除失败,文件或已不存在** @param bucketName* @throws Exception*/public void removeBucket(String bucketName) throws Exception {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());}/******************************  Operate Bucket End  ******************************//******************************  Operate Files Start  ******************************//*** 判断文件是否存在** @param bucketName 存储桶* @param objectName 文件名* @return*/public boolean isObjectExist(String bucketName, String objectName) {boolean exist = true;try {minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());} catch (Exception e) {exist = false;}return exist;}/*** 判断文件夹是否存在** @param bucketName 存储桶* @param objectName 文件夹名称* @return*/public boolean isFolderExist(String bucketName, String objectName) {boolean exist = false;try {Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(objectName).recursive(false).build());for (Result<Item> result : results) {Item item = result.get();if (item.isDir() && objectName.equals(item.objectName())) {exist = true;}}} catch (Exception e) {exist = false;}return exist;}/*** 根据文件前缀查询文件** @param bucketName 存储桶* @param prefix     前缀* @param recursive  是否使用递归查询* @return MinioItem 列表* @throws Exception*/public List<Item> getAllObjectsByPrefix(String bucketName,String prefix,boolean recursive) throws Exception {List<Item> list = new ArrayList<>();Iterable<Result<Item>> objectsIterator = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(recursive).build());if (objectsIterator != null) {for (Result<Item> o : objectsIterator) {Item item = o.get();list.add(item);}}return list;}/*** 获取文件流** @param bucketName 存储桶* @param objectName 文件名* @return 二进制流*/public InputStream getObject(String bucketName, String objectName) throws Exception {return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());}/*** 断点下载** @param bucketName 存储桶* @param objectName 文件名称* @param offset     起始字节的位置* @param length     要读取的长度* @return 二进制流*/public InputStream getObject(String bucketName, String objectName, long offset, long length) throws Exception {return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).offset(offset).length(length).build());}/*** 获取路径下文件列表** @param bucketName 存储桶* @param prefix     文件名称* @param recursive  是否递归查找,false:模拟文件夹结构查找* @return 二进制流*/public Iterable<Result<Item>> listObjects(String bucketName, String prefix,boolean recursive) {return minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(recursive).build());}/*** 使用MultipartFile进行文件上传** @param bucketName  存储桶* @param file        文件名* @param objectName  对象名* @param contentType 类型* @return* @throws Exception*/public ObjectWriteResponse uploadFile(String bucketName, MultipartFile file,String objectName, String contentType) throws Exception {InputStream inputStream = file.getInputStream();return minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).contentType(contentType).stream(inputStream, inputStream.available(), -1).build());}/*** 上传本地文件** @param bucketName 存储桶* @param objectName 对象名称* @param fileName   本地文件路径*/public ObjectWriteResponse uploadFile(String bucketName, String objectName,String fileName) throws Exception {return minioClient.uploadObject(UploadObjectArgs.builder().bucket(bucketName).object(objectName).filename(fileName).build());}/*** 通过流上传文件** @param bucketName  存储桶* @param objectName  文件对象* @param inputStream 文件流*/public ObjectWriteResponse uploadFile(String bucketName, String objectName, InputStream inputStream) throws Exception {return minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(inputStream, inputStream.available(), -1).build());}/*** 创建文件夹或目录** @param bucketName 存储桶* @param objectName 目录路径*/public ObjectWriteResponse createDir(String bucketName, String objectName) throws Exception {return minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(new ByteArrayInputStream(new byte[]{}), 0, -1).build());}/*** 获取文件信息, 如果抛出异常则说明文件不存在** @param bucketName 存储桶* @param objectName 文件名称*/public String getFileStatusInfo(String bucketName, String objectName) throws Exception {return minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build()).toString();}/*** 拷贝文件** @param bucketName    存储桶* @param objectName    文件名* @param srcBucketName 目标存储桶* @param srcObjectName 目标文件名*/public ObjectWriteResponse copyFile(String bucketName, String objectName,String srcBucketName, String srcObjectName) throws Exception {return minioClient.copyObject(CopyObjectArgs.builder().source(CopySource.builder().bucket(bucketName).object(objectName).build()).bucket(srcBucketName).object(srcObjectName).build());}/*** 删除文件** @param bucketName 存储桶* @param objectName 文件名称*/public void removeFile(String bucketName, String objectName) throws Exception {minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());}/*** 批量删除文件** @param bucketName 存储桶* @param keys       需要删除的文件列表* @return*/public void removeFiles(String bucketName, List<String> keys) {List<DeleteObject> objects = new LinkedList<>();keys.forEach(s -> {objects.add(new DeleteObject(s));try {removeFile(bucketName, s);} catch (Exception e) {log.error("批量删除失败!error:{}", e);}});}/*** 获取文件外链** @param bucketName 存储桶* @param objectName 文件名* @param expires    过期时间 <=7 秒 (外链有效时间(单位:秒))* @return url* @throws Exception*/public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) throws Exception {GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().expiry(expires).bucket(bucketName).object(objectName).build();return minioClient.getPresignedObjectUrl(args);}/*** 获得文件外链** @param bucketName* @param objectName* @return url* @throws Exception*/public String getPresignedObjectUrl(String bucketName, String objectName) throws Exception {GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(objectName).method(Method.GET).build();return minioClient.getPresignedObjectUrl(args);}/*** 将URLDecoder编码转成UTF8** @param str* @return* @throws UnsupportedEncodingException*/public String getUtf8ByURLDecoder(String str) throws UnsupportedEncodingException {String url = str.replaceAll("%(?![0-9a-fA-F]{2})", "%25");return URLDecoder.decode(url, "UTF-8");}/******************************  Operate Files End  ******************************/}

3、引入图片压缩的依赖

<dependency><groupId>net.coobird</groupId><artifactId>thumbnailator</artifactId><version>0.4.8</version>
</dependency>

4、开始进行缩略图的创建

@Autowired
private  MinIoUploadService minIoUploadService;
@Autowired
private  MinIOConfig minIOConfig;public int inertImageSlt(ImageVo imageVo) {// 获取上传文件的路径MultipartFile file = imageVo.getFileUrl();InputStream in = null;// 设置临时文件的存储路径// File.separator会根据系统的环境返回‘/’和 ‘\’,区分Linux 和 WinddomsString dirPath = "." + File.separator + "tempimg" + imageVo.getBh() + File.separator;try {if (file != null) {// 获取文件的输入流in = file.getInputStream();// 获取文件名,创建新的文件名String fileName = null;if(StringUtils.isNotEmpty(fileName)){String oldname = file.getOriginalFilename();String ext = oldname.substring(oldname.lastIndexOf("."));fileName = UUID.randomUUID().toString() + ext;}// 获得桶的名字String bucketname = minIOConfig.getBucketName();// 创建桶minIoUploadService.createBucket(bucketname);// 上传文件minIoUploadService.uploadFile(bucketname, fileName, file.getInputStream());// 手动拼接获取MinIO存储的路径String imgUrl = minIOConfig.getFileHost()+ "/"+ bucketname+ "/"+ fileName;// set进VO字段中imageVo.setZttpdz(imgUrl);// 创建临时目录,准备去把图片压缩成压缩图片String s = file.getOriginalFilename();File dir = new File(dirPath);if (!dir.exists()) {// 判断目录是否存在dir.mkdir();}File toFile = null;if (file.equals("") || file.getSize() <= 0) {file = null;} else {InputStream ins = null;ins = file.getInputStream();toFile = new File(dirPath + imageVo.getBh() + s);inputStreamToFile(ins, toFile);ins.close();}// 缩略图的临时存储路径String sltImgPath = dirPath + "slt" + imageVo.getBh() + s;// 进行图片的压缩Thumbnails.of(toFile).size(150, 150).toFile(sltImgPath);InputStream in1 = null;try {File file1 = new File(sltImgPath);in1 = new FileInputStream(file1);// 新建文件名String oldname = file.getOriginalFilename();String ext = oldname.substring(oldname.lastIndexOf("."));fileName = UUID.randomUUID().toString() + ext;minIoUploadService.uploadFile(bucketname, fileName, in1);// 手动拼接获取MinIO存储的路径String imgSltUrl = minIOConfig.getFileHost()+ "/"+ bucketname+ "/"+ fileName;imageVo.setZttpsltdz(imgSltUrl);} catch (Exception e) {log.error("----- {}", e);} finally {if (in1 != null) {in1.close();}}}} catch (Exception e) {log.error("----- {}", e);} finally {try {if (in != null)in.close();//删除临时文件File f = new File(dirPath);if (f.exists() && f.isDirectory()) {File[] files = f.listFiles();for (int i = 0; i < files.length; i++) {files[i].delete();}}if (f.listFiles().length == 0) {f.delete();}} catch (IOException e) {log.error("----- {}", e);}}return jzkdztMapper.insertJzkdZt(imageVo);
}

4、引用1

// 把文件流转成文件
private static void inputStreamToFile(InputStream ins, File file) {try {OutputStream os = new FileOutputStream(file);int bytesRead = 0;byte[] buffer = new byte[8192];while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {os.write(buffer, 0, bytesRead);}os.close();ins.close();} catch (Exception e) {e.printStackTrace();}
}

MinIO中上传缩略图相关推荐

  1. MinIo 安装及其集成到java中上传下载图片信息

    MinIo 安装及其集成到java中上传下载图片信息 win 下安装 下载链接:https://min.io/download#/windows 下载好后cmd打开控制台 输入:minio.exe s ...

  2. android使用webview上传文件,Android项目中如何在webview页面中上传文件

    Android项目中如何在webview页面中上传文件 发布时间:2020-11-26 15:56:27 来源:亿速云 阅读:68 作者:Leah 本篇文章为大家展示了Android项目中如何在web ...

  3. 查询mysql上传大小限制_解决数据库phpmyadmin中上传最大限制:2,048 KB

    解决数据库phpmyadmin中上传最大限制:2,048 KB 一.修改php.ini文件. 找到php.ini搜索这3个地方 1.查找post_max_size,指通过表单POST给PHP的所能接收 ...

  4. 织梦后台上传文章的php文件是那个,如何在织梦文章中上传视频及调用视频

    在上一篇文章中,我弄好了zblog如何在文章中上传视频和调用视频,那么因为我有很多个站,所以,这篇文章研究一下如何在织梦系统的文章中进行上传视频和调用视频,上传视频的话,一般推荐直接FTP传到自己的服 ...

  5. ASP.NET中上传下载文件

    ASP.NET中上传下载文件 //检查上传文件不为空 if(File1.PostedFile!=null) { stringnam=File1.PostedFile.FileName; //取得文件名 ...

  6. xshell下载mysql到本地文件_在Xshell中上传下载文件到本地(linux中从多次ssh登录的dbserver里面的文件夹)-Go语言中文社区...

    在Xshell中上传下载文件到本地(linux中从多次ssh登录的dbserver里面的文件夹) 1 列出所有需要copy的sh文件 -bash-4.1$ ll /mysqllog/osw/*.sh ...

  7. mindspore学习之使用obsutil工具向桶中上传数据

    我们在使用obs服务时,一般是自己建立文件夹,但是如果我们的数据集包含大量文件夹时,自己建立似乎不是一个好办法,那么如何批量向桶内的文件夹中上传数据呢,今天我们就来见识一下obsutil这个小工具的厉 ...

  8. java上传和下载文件代码_JavaWeb中上传和下载文件实例代码

    一丶先引入上传下载的lib 二丶上传的的servlet package com.test.action; import java.io.file; import java.io.fileoutputs ...

  9. 随便说说:在ASP.NET应用程序中上传文件

    在Web程序中上传文件是很常见的需求.利用HTTP协议上传文件的方式非常有限,最常见的莫过于使用<input type="file" />元素进行上传.这种上传方式会将 ...

最新文章

  1. 张雨生林志炫高音对比
  2. 关于arcgis发布wfs问题
  3. mysql oracle sql区别吗_mysql数据库的SQL语句和oracle的有什么区别?详细点
  4. 八数码(康拓展开标记)及类似题
  5. 湖南大学计算机学院张柏杨,缪力-湖大信息科学与工程学院
  6. python 开闭原则_Python 装饰器@,对函数进行功能扩展操作示例【开闭原则】
  7. 软件测试实验1:JUnit、Hamcrest、Eclemma
  8. apache 搭建PHP多站点
  9. 数据结构与算法14-栈和队列练习题
  10. javascrit 数组方法总结(数组对象、栈,队列、重排序、操作数组方法、位置方法、归并方法、迭代方法)
  11. 【转载】Java并发编程:volatile关键字解析 by 海子
  12. 网站SEO实践之 - seo引流怎么选有流量的关键词
  13. Android 仿钉钉、微信 群聊组合头像
  14. Android后台Kill(二):ActivityManagerService与App现场恢复机制
  15. 1.Hadoop入门
  16. 【C语言-进阶】指针进阶(2)
  17. 上网使用随身wifi与路由器有何不同?
  18. anaconda的令牌是啥_Anaconda是什么?香吗?
  19. 在线制作流程图的实用工具网站
  20. iOS 判断是否安装SIM卡

热门文章

  1. iso硬盘安装 凤凰os_系统之家ISO硬盘安装图解
  2. ADB将外置TF储存卡融合本机ROM(内部储存)
  3. 分治算法——Karastsuba算法
  4. 1100. 校庆 (25 分)
  5. Android中APK安装流程解析
  6. keil中c语言bit怎么用,关于keil多c文件工程中bit变量的声明定义问题
  7. 用了这个,我追到了自己的女神:Mac版QQ半自动发送情话
  8. vue项目实现单/多文件下载和打包压缩下载
  9. 电脑双屏显示变单屏后部分程序无法在当前屏幕显示的问题
  10. 你的链上资产存储安全吗?交易自由吗?