public void download(String pathUrl, HttpServletResponse response) throws Exception {
String key = pathUrl.replace(minIOConfigProperties.getEndpoint()+"/","");
int index = key.indexOf(separator);
String bucketName = key.substring(0,index);
String filetName = key.substring(index+1);
String encodedFileName = new String(filetName.getBytes("utf-8"), "ISO8859-1");
// 根据文件夹名称和文件名称找到对应文件对象
ObjectStat stat = minioClient.statObject(bucketName, filetName);
byte[] buffer = new byte[1024];
int length = (int) stat.length();
try (InputStream inputStream = minioClient.getObject(bucketName, filetName);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(length)) {
ByteStreams.copy(inputStream, outputStream);
buffer = outputStream.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
String[] pathSegments = filetName.split("/");
for (int i = 0; i < pathSegments.length; i++) {
pathSegments[i] = URLEncoder.encode(pathSegments[i], "UTF-8");
}
// 拼接编码后的路径字符串
String encodedPath = String.join("/", pathSegments);
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
// response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + URLEncoder.encode(filetName, "UTF-8"));
response.setHeader("Content-disposition", "attachment; filename=" + new String(encodedPath.getBytes("utf-8"), "ISO8859-1"));
// response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(filetName, "UTF-8"));
response.getOutputStream().write(buffer);
response.flushBuffer();
response.getOutputStream().close();
}
BASE64编码来解决中文乱码的问题
import org.springframework.util.StreamUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
// 其他代码...
@GetMapping("/downloadWord")
public ResponseEntity<byte[]> downloadWord(@RequestParam String path, HttpServletResponse response) {
try {
// 初始化Minio客户端
MinioClient minioClient = new MinioClient(minioEndpoint, minioAccessKey, minioSecretKey);
// 获取Word文件流
InputStream inputStream = minioClient.getObject(path).getObjectContent();
// 将输入流转换为字节数组
byte[] content = StreamUtils.copyToByteArray(inputStream);
// 使用 BASE64 编码文件名
String encodedFilename = Base64.getEncoder().encodeToString(path.getBytes("UTF-8"));
// 设置响应头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", "filename=\"" + encodedFilename + "\"");
// 返回ResponseEntity
return new ResponseEntity<>(content, headers, HttpStatus.OK);
} catch (IOException | MinioException | IllegalArgumentException e) {
e.printStackTrace();
// 处理异常情况,返回错误信息
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
}
}
如果即使使用了 URLEncoder.encode 方法仍然出现中文乱码问题,可能是由于浏览器或其他客户端在解析URL时出现了问题。
在这种情况下,你可以尝试手动设置 Content-Disposition 头部,并使用 BASE64 编码来传递文件名。以下是更新后的代码:
import org.springframework.util.StreamUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
// 其他代码...
@GetMapping("/downloadWord")
public ResponseEntity<byte[]> downloadWord(@RequestParam String path, HttpServletResponse response) {
try {
// 初始化Minio客户端
MinioClient minioClient = new MinioClient(minioEndpoint, minioAccessKey, minioSecretKey);
// 获取Word文件流
InputStream inputStream = minioClient.getObject(path).getObjectContent();
// 将输入流转换为字节数组
byte[] content = StreamUtils.copyToByteArray(inputStream);
// 使用 BASE64 编码文件名
String encodedFilename = Base64.getEncoder().encodeToString(path.getBytes("UTF-8"));
// 设置响应头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", "filename=\"" + encodedFilename + "\"");
// 返回ResponseEntity
return new ResponseEntity<>(content, headers, HttpStatus.OK);
} catch (IOException | MinioException | IllegalArgumentException e) {
e.printStackTrace();
// 处理异常情况,返回错误信息
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
}
}
如果即使使用BASE64编码方式依然无法解决中文文件名乱码的问题,可能是由于浏览器对于Content-Disposition中的filename*参数支持不完善。
在这种情况下,你可以尝试使用一种更为保守的方式,即先将文件名进行URL编码,然后再通过手动设置Content-Disposition头部来传递。以下是更新后的示例代码:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
@Controller
public class FileDownloadController {
@GetMapping("/download")
public void download(String pathUrl, HttpServletResponse response) throws IOException {
// 获取文件名
String fileName = "文件名.txt"; // 从 pathUrl 中获取文件名或自定义文件名
// 创建连接
URL url = new URL(pathUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
// 获取输入流
InputStream inputStream = connection.getInputStream();
// 设置响应头
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=" + encodeFilename(fileName));
// 获取输出流
response.getOutputStream().write(inputStream.readAllBytes());
inputStream.close();
}
// 将文件名进行URL编码
private String encodeFilename(String fileName) {
try {
return URLEncoder.encode(fileName, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return fileName; // 如果编码失败,则返回原文件名
}
}
}
如果使用URL编码后依然出现中文乱码的问题,可能是由于浏览器对于Content-Disposition中的编码方式支持不完善导致的。在这种情况下,还可以尝试使用ISO-8859-1编码方式对文件名进行编码,并手动设置Content-Disposition头部。
以下是使用ISO-8859-1编码方式对文件名进行编码,并手动设置Content-Disposition头部的示例代码:
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
@Controller
public class FileDownloadController {
@GetMapping("/download")
public void download(String pathUrl, HttpServletResponse response) throws IOException {
// 获取文件名
String fileName = "文件名.txt"; // 从 pathUrl 中获取文件名或自定义文件名
// 创建连接
URL url = new URL(pathUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
// 获取输入流
InputStream inputStream = connection.getInputStream();
// 设置响应头
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=" + encodeFilename(fileName));
// 获取输出流
OutputStream outputStream = response.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(outputStream);
// 缓冲区
byte[] buffer = new byte[1024];
int len;
// 写入文件内容
while ((len = inputStream.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
// 关闭流
bos.close();
inputStream.close();
}
// 将中文文件名转换为ISO-8859-1编码形式
private String encodeFilename(String fileName) {
try {
return new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return fileName; // 如果编码失败,则返回原文件名
}
}
}