一 为什么要写下载?
正常使用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):
- 直接将文件数据写入到响应输出流中,避免了先将整个文件读取到内存中的开销。
- 可以设置 HTTP 响应头来控制浏览器的下载行为,如强制下载、文件名等。
- 适用于各种类型的文件下载需求,简单易用。
FastByteArrayOutputStream
是一个自定义的字节数组输出流实现,主要用于提高 I/O 操作的性能。它与标准的ByteArrayOutputStream
相比,有以下几个特点:
-
内部使用了一个可变大小的字节数组来存储数据,而不是使用固定大小的数组。这样可以减少内存分配和复制的开销。
-
在写入数据时,它会先检查当前数组是否足够大,如果不够则会自动扩展数组。这样可以避免频繁的数组扩容操作。
-
它还提供了一些额外的方法,如
toByteArrayUnsafe()
可以直接返回内部数组,而不需要复制数据。
相比于标准的 ByteArrayOutputStream
,FastByteArrayOutputStream
在处理大量数据时能提供更好的性能。这在文件下载这种场景下非常有用,因为可以减少内存分配和复制的开销,从而提高整体的下载速度。
在示例代码中,使用 FastByteArrayOutputStream
来缓存从 Minio 获取的文件数据,然后再一次性写入到响应输出流中。这种方式可以避免将整个文件一次性读取到内存中,从而降低内存使用。