Minio的图片下载

一 为什么要写下载?

正常使用Minio的时候,其实是不用单独再写下载功能的,因为使用Minio上传的时候,可以再返回结果里带上地址,可直接点击地址进行下载,可如果现在既要预览又要下载,就需要单独写一个下载功能.

1 代码如下

Minio使用的初始化

    private void init() {minioClient = MinioClient.builder().endpoint(config.getMinioEndPoint()).credentials(config.getMinioAccessKey(), config.getMinioSecretKey()).build();}

Minio图片下载的业务代码

    @Override//下载public void download(String folderPath, HttpServletResponse res,String fileName) {GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(config.getMinioBucketName()).object(folderPath).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.addHeader("Content-Disposition", "attachment;fileName=" + fileName);try (ServletOutputStream stream = res.getOutputStream()) {stream.write(bytes);stream.flush();}}} catch (Exception e) {e.printStackTrace();}}

Minio的下载接口 

@GetMapping("download")@Operation(summary = "下载文件")public void download(@RequestParam String fileName, HttpServletResponse res) {String url = ossService.getUrl(fileName);String[] parts = url.split("/");int fileIndex = parts.length - 1;String name = parts[fileIndex];String filePath = String.join("/", Arrays.copyOfRange(parts, 4, fileIndex));String folderPath = filePath + "/" + name;OssFactory.build().download(folderPath, res, fileName);}

2 总结

  • 初始化Minio的使用.
  • 通过 Minio 客户端获取指定路径的对象数据,并将其读取到内存中的字节数组中。
  • 设置 HTTP 响应头中的 Content-Disposition 为 attachment,告诉浏览器将响应内容作为附件下载。同时设置文件名 fileName
  • 获取 HTTP 响应输出流(ServletOutputStream)。
  • 将之前读取的字节数组写入到响应输出流中。
  • 刷新输出流,将数据发送给客户端。
    •  响应输出流(ServletOutputStream):
    1. 直接将文件数据写入到响应输出流中,避免了先将整个文件读取到内存中的开销。
    2. 可以设置 HTTP 响应头来控制浏览器的下载行为,如强制下载、文件名等。
    3. 适用于各种类型的文件下载需求,简单易用。
  • FastByteArrayOutputStream 是一个自定义的字节数组输出流实现,主要用于提高 I/O 操作的性能。它与标准的 ByteArrayOutputStream 相比,有以下几个特点:
  1. 内部使用了一个可变大小的字节数组来存储数据,而不是使用固定大小的数组。这样可以减少内存分配和复制的开销。

  2. 在写入数据时,它会先检查当前数组是否足够大,如果不够则会自动扩展数组。这样可以避免频繁的数组扩容操作。

  3. 它还提供了一些额外的方法,如 toByteArrayUnsafe() 可以直接返回内部数组,而不需要复制数据。

相比于标准的 ByteArrayOutputStreamFastByteArrayOutputStream 在处理大量数据时能提供更好的性能。这在文件下载这种场景下非常有用,因为可以减少内存分配和复制的开销,从而提高整体的下载速度。

在示例代码中,使用 FastByteArrayOutputStream 来缓存从 Minio 获取的文件数据,然后再一次性写入到响应输出流中。这种方式可以避免将整个文件一次性读取到内存中,从而降低内存使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/20837.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【思考】服务的吞吐量与请求耗时的关系

吞吐量即服务1s内可以处理的最大请求数,即最大可以支撑的QPS;请求耗时就更好理解了,即处理一次请求所需要耗费的时间。 明显这两个指标都是用来衡量服务的性能的,但两者之间的关系是什么呢?他们之间是否存在一些相互的…

spdlog日志库源码:输出通道sink

概述 在 spdlog 日志库中,sinks 并不是一个单独的类,而是一系列类的集合,这些类以基类-派生类的形式组织,每一个 sink 派生类代表了一种输出日志消息的方式。输出目标可以是普通文件、标准输出 (stdout)、标准错误输出 (stderr)、…

sqoop操作

介绍 sqoop是隶属于Apache旗下的, 最早是属于cloudera公司的,是一个用户进行数据的导入导出的工具, 主要是将关系型的数据库(MySQL, oracle...)导入到hadoop生态圈(HDFS,HIVE,Hbase...) , 以及将hadoop生态圈数据导出到关系型数据库中 操作 将数据从mysql中导入到HDFS中 1.全量…

Pytest框架中的Setup和Teardown功能

在 pytest 测试框架中,setup 和 teardown是用于在每个测试函数之前和之后执行设置和清理的动作,而pytest 实际上并没有内置的 setup 和 teardown 函数,而是使用了一些装饰器或钩子函数来实现类似的功能。 学习目录 钩子函数(Hook…

详解 Scala 的模式匹配

一、基本语法 Scala 中的模式匹配类似于 Java 中的 switch 语法,但是功能更强大 /**[var a / def func() ] var_name match {case value1 > statement1case value2 > statement2case value3 > statement3case _ > defaultOP} */ object TestMatchCase…

Python——cv2 判断图像读取内容是否为空

import cv2 pic_path"xxx.jpg" imagecv2.imread(pic_path) if None image:print("图片为空") else:print("图片不为空")

ubuntu上zsh与bash切换

在Ubuntu上切换zsh和bash,你可以使用命令行。 切换到zsh: chsh -s $(which zsh)切换回bash: chsh -s $(which bash)注意:chsh命令可能需要你输入你的用户密码。 如果你想立即启动新shell,而不用重启,可以运行: ex…

java中的线程安全的容器

ReentrantLock 和 Condition 都是基于 AbstractQueuedSynchronizer (AQS) 实现的。 以下是 ReentrantLock 与 AQS 的关系: ReentrantLock 状态管理:ReentrantLock 通过 AQS 的 state 变量来表示锁的状态。状态为 0 表示锁未被持有,状态为 1…

【python】YOLO目标检测txt标签转xml,支持与原xml标签融合

需求: 利用现有yolo模型权重实现自动标注功能,即使用yolov5源码中的detect.py对待标注图像执行推理任务,并使用--save-txt保存标签文件,然后使用本文python代码直接将detect.py生成的txt标签转为xml标签,最后再使用la…

SAP PP学习笔记14 - MTS(Make-to-Stock) 按库存生产(策略10),以及生产计划的概要

上面讲了SAP里面的基础知识,BOM,作业手顺(工艺路线),作业区(工作中心),MRP,MPS等概念,现在该到用的时候了。 SAP PP学习笔记07 - 简单BOM,派生BO…

5门编程语言哪个好一点:深入剖析与选择指南

5门编程语言哪个好一点:深入剖析与选择指南 在编程的广阔领域中,各种语言如繁星般璀璨,各有其独特之处。对于初学者或寻求转型的开发者来说,如何选择一门合适的编程语言往往令人头疼。本文将针对五门热门编程语言进行详细剖析&am…

STC8增强型单片机进阶开发--独立按键

知不足而奋进 望远山而前行 文章目录 目录 文章目录 前言 目标 内容 原理图 按键消抖 软件设计 要求 分析 实现单个按钮 实现多个按钮 使用位操作存储状态 总结 前言 本次学习旨在探索按键操作及按键消抖的原理和实现方法。通过学习原理图、按键消抖的三种方法以及软件设计的要…

NXP RT1060学习总结 - 基础CAN功能

1、RT1060-CAN功能简介 这里使用的是RT1060系列的1064芯片进行开发,使用的是官方提供的开发板;提供的CAN外设为CAN2,使用CAN2的好处是IO与CAN3可以互相映射,而CAN3是具备CAN-FD功能。 2、CAN IO初始化 static void can2_gpio_c…

什么是Java泛型?它有什么作用

Java泛型(Generics)是一种允许在定义类、接口和方法时使用类型参数的机制。泛型提供了一种机制,使得代码可以对多种类型的对象进行操作,而无需进行类型转换。 Java泛型的作用 类型安全:通过在编译时进行类型检查&…

如何选择D类音频放大器(数字功率放大器)

1 简介 多年来,音频内容一直在不断发展。从当地唱片店购买 12 英寸 LP 黑胶唱片的时代已经成为过去,现在我们通过流式传输几乎可即时播放云端的任何内容。虽然一些音频爱好者会为了获得新奇体验而重拾黑胶唱片,但今天绝大多数的音频都是以数…

JVM学习笔记(持续更新)

JDK、JRE、JVM区别? 类加载过程 装载 验证 准备 解析 初始化 类加载器分类 双亲委派模型 如何打破双亲委派模型? 自定义类加载器,集成ClassLoader类重写loadClass,如Tomcat JVM内存模型 JVM 需要使用计算机的内存,Java 程序…

【LeetCode 101】对称二叉树

1. 题目 2. 分析 这道题比较经典。我又一次做错了,这次是花了20min都没有做出来。 最开始我的思想就是,递归比较左根节点的左子树和右根节点的右子树是否对称即可,然后觉得能解决问题了,便动手coding。哪知道,又碰到了…

电源滤波器怎么选用

电源滤波器怎么选用 滤波器应用场景及作用第一步:第二步:第三步:第四步: 滤波器应用场景及作用 可以有效解决EMC测试无法通过、端口防护、滤除干扰、设备保护等问题 主要功能有: 1、降低主电源谐波; 2、保护驱动装置电力电子元件…

算法人生(18):从神经网络的“剪枝策略”看“怎么找回时间”

IT人的工作和生活难平衡这事,到底要怎么解决呢,让我们从神经网络的“剪枝策略”中找点灵感吧! 剪枝策略是指训练和优化深度神经网络时采取的一种技术,从名字就知道,它就像修剪树木一样,去除不必要的枝叶&a…

枣庄高防服务器如何确保数据的安全保护?

如何利用枣庄高防服务器确保数据的安全保护? 在当今信息时代,数据安全已经成为企业和个人都需要面对的重要问题。为了保障数据的安全,许多企业选择枣庄高防服务器,其强大的安全防护能力为用户提供了可靠的保障。而为了最大程度地…