Java下载文件时文件名乱码问题解决办法

关于Java下载文件时出现文件名乱码问题的解决办法,我将提供以下完整攻略:

问题描述

当我们使用Java程序进行文件下载时,有时会出现文件名乱码的问题。这是因为在Http响应头中,如果文件名中含有中文等非英文字符,服务器会使用UTF-8对文件名进行编码,而Java程序默认使用ISO-8859-1来解码文件名,因此就会出现乱码问题。

解决办法

1.获取文件名编码字符集

可以通过获取Http响应头中“Content-Disposition”字段的值来获取文件名编码字符集。如下代码示例:

URL url = new URL(fileUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
InputStream inputStream = conn.getInputStream();
String contentDis = conn.getHeaderField("Content-Disposition");
String charset = "ISO-8859-1"; // 默认编码字符集
if (contentDis != null && contentDis.contains("filename=")) {
    String[] tmp = contentDis.split("filename=");
    if (tmp.length > 1) {
        String fileName = tmp[1].replaceAll("\"", "");
        fileName = URLDecoder.decode(fileName, "UTF-8");
        charset = new String(fileName.getBytes("ISO-8859-1"), "UTF-8");
    }
}

2.设置正确的编码字符集

在获取到文件名编码字符集后,就可以将Java程序的编码字符集设置为正确的编码字符集。如下代码示例:

String userAgent = request.getHeader("User-Agent");
String fileName = URLEncoder.encode(file.getName(), charset);
if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
    fileName = java.net.URLEncoder.encode(file.getName(), charset);
}
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", String.format("attachment;filename=\"%s\"", fileName));
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
OutputStream outputStream = response.getOutputStream();
byte[] buffer = new byte[1024];
int length = 0;
while ((length = inputStream.read(buffer)) != -1) {
    outputStream.write(buffer, 0, length);
}
outputStream.flush();

这里需要注意的是,在设置Http响应头“Content-Disposition”字段的值时,需要使用正确的编码字符集进行编码,否则下载下来的文件名仍然会是乱码。

示例

假设有一个文件下载的请求,请求路径为“http://www.example.com/download?fileId=1”,Java程序需要从该链接下载指定的文件,并将文件名以附件形式返回给用户进行下载,那么具体的实现如下所示:

@RequestMapping(value = "/download", produces = "application/json;charset=UTF-8")
@ResponseBody
public String downloadFile(@RequestParam("fileId") Integer fileId, HttpServletRequest request,
    HttpServletResponse response) {
    File file = getFileById(fileId); // 根据文件id获取文件对象
    if (!file.exists()) { // 如果文件不存在,则返回文件不存在的错误信息
        return "{'success':false,'msg':'File not existed!'}";
    }
    try {
        URL url = new URL("http://www.example.com/download?fileId=" + fileId);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        InputStream inputStream = conn.getInputStream();
        String contentDis = conn.getHeaderField("Content-Disposition");
        String charset = "ISO-8859-1";
        if (contentDis != null && contentDis.contains("filename=")) {
            String[] tmp = contentDis.split("filename=");
            if (tmp.length > 1) {
                String fileName = tmp[1].replaceAll("\"", "");
                fileName = URLDecoder.decode(fileName, "UTF-8");
                charset = new String(fileName.getBytes("ISO-8859-1"), "UTF-8");
            }
        }
        String userAgent = request.getHeader("User-Agent");
        String fileName = URLEncoder.encode(file.getName(), charset);
        if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
            fileName = java.net.URLEncoder.encode(file.getName(), charset);
        }
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", String.format("attachment;filename=\"%s\"", fileName));
        InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
        OutputStream outputStream = response.getOutputStream();
        byte[] buffer = new byte[1024];
        int length = 0;
        while ((length = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, length);
        }
        outputStream.flush();
        outputStream.close();
        inputStream.close();
    } catch (IOException e) { // 如果下载过程中发生异常,则返回下载失败的错误信息
        e.printStackTrace();
        return "{'success':false,'msg':'Download failed!'}";
    }
    return "{'success':true,'msg':'Download successfully!'}";
}

在上述示例中,“getFileById()”方法用于根据文件id获取文件对象,具体实现可以根据业务需要自行编写。另外需要注意的是,需要将请求头中的“User-Agent”字段用作判断浏览器类型的标志来对文件名进行编码,这是因为不同浏览器对于文件名编码和解码方式是有所不同的。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java下载文件时文件名乱码问题解决办法 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • 详解微信小程序实现仿微信聊天界面(各种细节处理)

    详解微信小程序实现仿微信聊天界面(各种细节处理) 1. 概述 本攻略旨在利用微信小程序的基础组件和API实现仿微信聊天界面的功能。其中包括对聊天记录的渲染、语音和图片消息的处理、滚动条的实现、输入框的处理以及底部工具栏的实现等。 2. 渲染聊天记录 在小程序中,我们可以使用wx:for将聊天记录数组渲染到页面中。为了使聊天界面更加真实,我们需要对每一条聊天记…

    Java 2023年5月23日
    00
  • mybatis 如何利用resultMap复杂类型list映射

    MyBatis是一款流行的Java ORM框架。我们可以使用它来实现数据的持久化操作。在MyBatis中,很多查询的结果都是List对象,但是有时候我们需要将复杂的结果集映射到List对象中。这个时候我们可以使用MyBatis中的ResultMap进行映射。 ResultMap是 MyBatis 映射语句中最重要的元素之一。 它可以很好地将复杂类型的结果集,…

    Java 2023年5月20日
    00
  • 微信小程序HTTP接口请求封装的实现

    微信小程序HTTP接口请求封装可以让开发者在进行后端请求时,不需要每次都编写相同的请求代码,提高了开发效率和代码可维护性。以下是实现步骤: 1.创建请求封装工具类 可以创建一个名为request.js的文件,使用ES6语法定义一个请求类,通过wx.request来进行请求。请求封装可以支持对请求头、请求体、请求地址、请求类型等进行配置。在进行请求后,利用Pr…

    Java 2023年5月23日
    00
  • 使用Easyui实现查询条件的后端传递并自动刷新表格的两种方法

    使用EasyUI实现查询条件的后端传递并自动刷新表格,一般有两种方法可以实现。 方法一:使用表单的submit事件以及datagrid的load方法 1. 在页面中定义查询表单以及datagrid 在页面中定义一个查询表单,表单中包含了查询条件,以及一个查询按钮。同时,定义一个datagrid用于表格的展示。 <form id="queryF…

    Java 2023年6月15日
    00
  • Java中的Random()函数及两种构造方法

    Java中的Random()函数及两种构造方法 在Java中,java.util.Random是一个用于生成伪随机数的类。它有两种构造方法,可以实现不同用途的随机数生成。 1. Random()函数 Random()函数是java.util.Random类的默认构造方法。该构造方法将当前时间戳作为种子,可以生成一个伪随机数: import java.util…

    Java 2023年5月26日
    00
  • eclipse入门之创建第一个web程序(jsp测试环境)

    下面就是“eclipse入门之创建第一个web程序(jsp测试环境)”的完整攻略: 准备工作 安装JDK,配置环境变量 下载并安装eclipse 创建Web项目 打开eclipse,选择”File” -> “New” -> “Dynamic Web Project” 在新建项目页面中输入项目名、选择项目保存路径、选择目标运行环境(J2EE 6 v…

    Java 2023年6月15日
    00
  • 30道有趣的JVM面试题(小结)

    我将根据“30道有趣的JVM面试题(小结)”这篇文章,给出一份完整的攻略,包括每道面试题的解析和答案。 1. 什么是JVM? JVM即Java Virtual Machine,Java虚拟机。它是一种能够在各种平台上运行Java程序的虚拟机。JVM可以将Java代码编译成字节码,然后在不同的平台上通过解释执行这些字节码以实现Java程序的运行。 2. Jav…

    Java 2023年5月19日
    00
  • java Timer 定时每天凌晨1点执行任务

    Java Timer是Java中的一个计时器工具,可以用来在特定时间间隔内执行指定任务。下面是Java Timer实现每天凌晨1点执行任务的攻略: 步骤一:创建Timer对象 在Java中,我们需要使用java.util.Timer类来创建一个计时器对象。首先,需要导入java.util.Timer和java.util.TimerTask这两个包。 impo…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部