springboot 下载从minio里下载文件 文件名称中文乱码

    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; // 如果编码失败,则返回原文件名
        }
    }
}

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用 Spring Boot 来实现一个接收 HTTP 请求,并使用 MinIO 完成文件的分片下载。下面是一个示例代码: ```java import io.minio.MinioClient; import io.minio.errors.*; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @RestController @RequestMapping("/download") public class MinioDownloadController { @Value("${minio.accessKey}") private String accessKey; @Value("${minio.secretKey}") private String secretKey; @Value("${minio.endpoint}") private String endpoint; @GetMapping("/{bucketName}/{objectName}") public ResponseEntity<InputStreamResource> downloadFile(@PathVariable String bucketName, @PathVariable String objectName, HttpServletRequest request, HttpServletResponse response) { try { MinioClient minioClient = new MinioClient(endpoint, accessKey, secretKey); String contentType = minioClient.statObject(bucketName, objectName).contentType(); response.setContentType(contentType); response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + objectName + "\""); minioClient.getObject(bucketName, objectName) .forEach(d -> { try { response.getOutputStream().write(d); } catch (IOException e) { e.printStackTrace(); } }); response.flushBuffer(); } catch (InvalidEndpointException | InvalidPortException | InvalidBucketNameException | NoSuchAlgorithmException | InsufficientDataException | IOException | InvalidKeyException | NoResponseException | ErrorResponseException | InternalException | InvalidArgumentException e) { e.printStackTrace(); } return new ResponseEntity<>(HttpStatus.OK); } } ``` 在上述代码中,你需要在 Spring Boot 的配置文件中添加以下配置: ```properties minio.accessKey=your-access-key minio.secretKey=your-secret-key minio.endpoint=your-minio-endpoint ``` 然后,你可以在 `MinioDownloadController` 类中创建一个路由为 `/download/{bucketName}/{objectName}` 的接口来处理下载请求。该接口会根据传入的 `bucketName` 和 `objectName` 参数从 MinIO 中获取文件,并将文件流写入响应的输出流中,从而实现文件的分片下载。 希望这个示例对你有帮助!如果你有任何其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值