通过URL下载文件,使用原始文件名乱码问题

文章讲述了如何通过Java编程下载URL文件时遇到的文件名乱码问题,通过分析发现服务端可能未正确设置文件名编码,解决方案是将接收到的文件名转换为字节数组,然后用目标编码格式(如UTF-8)重新转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、问题描述

需求:通过URL下载文件,并保持在上传时的文件名
**问题:**通过下载,文件可以正常打开,但是名称为乱码!谷歌浏览器通过URL进行下载,则可展示正常的名字。

二、初始代码

public boolean downApprovalFile(String url) {
        try{
        HttpResponse execute = HttpRequest.get(url)
                .charset("ISO8859-1")  //设置没有效果,无论如何设置,文件名均乱码(考虑:服务端未根据这个参数进行自动设置)
                .execute();  //此方法位hutool工具类提供的方法,使用Java自带的URL下载也为乱码。
        InputStream inputStream = execute.bodyStream();
        String header = execute.header("Content-Disposition");

        String[] split = header.split(";");
        String filename= split[1].substring(9);
        
        OutputStream outputStream = new FileOutputStream(FileUtil.file("D:/temp"+File.separator+filename));

        IOUtils.copy(inputStream,outputStream);  //此方法位hutool工具类提供的方法,下载

        //long size = HttpUtil.downloadFile(url, FileUtil.file("D:/temp")); //此方法位hutoo工具类提供的下载方法,下载的结果也使乱码!
        long size = HttpUtil.download(url, outputStream, true);
        return true;
        }catch (Exception e){
            e.printStackTrace();
            log.error("【下载本地失败!】");
            return false;
        }
    }

使用上面的两个下载方法,均为乱码,查度娘也没找到解决办法,大多都是指定一个名称进行下载。

三、解决办法

进行传输时,实际是流进行传输,所以可以将传输的名称转换成byte[]数组,然后再以特定的编码格式转换回来,代码示例如下:

public boolean downApprovalFile(String url) {
        try{
        HttpResponse execute = HttpRequest.get(url)
                //.charset("ISO8859-1")  //设置没有效果,无论如何设置,文件名均乱码(考虑:服务端未根据这个参数进行自动设置)
                //.charset("UTF-8")
                .execute();
        InputStream inputStream = execute.bodyStream();
        String header = execute.header("Content-Disposition");

        String[] split = header.split(";");
        String substring = split[1].substring(9);
        byte[] bytes = substring.getBytes("ISO8859-1"); // 此参数必须,为服务端提供下载时设置文件名的编码格式(ps:我是一个一个测试出来的,因为不确定服务器给转成什么格式了)

        String filename = new String(bytes, "UTF-8"); // 转成你本地能识别的编码格式!我本地配置的UTF-8

        OutputStream outputStream = new FileOutputStream(FileUtil.file("D:/temp"+File.separator+filename));

        IOUtils.copy(inputStream,outputStream); //此方法下载,不出现乱码!

        //long size = HttpUtil.downloadFile(url, FileUtil.file("D:/temp"));
        long size = HttpUtil.download(url, outputStream, true); //该方法仍乱码,hutool内部没有做处理,也没有提供可用api
        return true;
        }catch (Exception e){
            e.printStackTrace();
            log.error("【下载本地失败!】");
            return false;
        }
    }

网上没有找到解决此情况的乱码问题,特此记录!

### Kettle SFTP 下载文件时中文文件名乱码解决方案 在使用 Kettle 进行 SFTP 文件下载的过程中,如果遇到中文文件名乱码问题,通常是因为字符集编码不匹配所导致。以下是针对该问题的具体分析与解决方案: #### 1. 字符集编码问题的根本原因 Kettle 默认使用的字符集可能无法正确解析远程服务器上的中文文件名。SFTP 协议本身支持多种字符集,但如果客户端(即 Kettle)未指定正确的字符集,则可能导致文件名显示异常[^1]。 #### 2. 配置 Kettle 的字符集选项 为了确保 Kettle 能够正确处理中文文件名,在配置 SFTP 步骤时需注意以下几点: - **设置全局环境变量** 可以通过修改 ` Spoon.bat` 或 `spoon.sh` 来设置 JVM 参数 `-Dfile.encoding=UTF-8`,从而强制 Kettle 使用 UTF-8 编码。例如,在 Linux 环境下编辑 `spoon.sh` 并添加如下内容: ```bash export JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8" ``` - **调整 SFTP 插件的编码属性** 如果 Kettle 提供了特定于 SFTP 的编码选项(部分版本支持),可以在插件配置界面手动设定字符集为 UTF-8 或 GBK。具体操作路径为:进入 SFTP Step 设置窗口 -> Advanced Options -> Character Encoding[^3]。 #### 3. 自定义脚本解决乱码问题 对于某些旧版 Kettle 不支持直接更改字符集的情况,可以借助自定义脚本来完成文件传输前后的编码转换工作。例如,利用 Java 实现文件名解码逻辑并集成到 Kettle 流程中: ```java import java.io.File; import java.nio.charset.Charset; public class FileNameDecoder { public static void main(String[] args) throws Exception { String encodedFileName = "111490-%E4%B8%80%E8%BD%B4%E8%BE%B9%E6%89%BF(%E5%AF%BC%E5%90%91%E8%BE%B9%E6%89%BF).jpg"; // URL-encoded 中文名称 Charset sourceCharset = Charset.forName("UTF-8"); Charset targetCharset = Charset.forName("GBK"); byte[] bytes = encodedFileName.getBytes(sourceCharset); String decodedName = new String(bytes, targetCharset); File outputFile = new File(decodedName); if (!outputFile.exists()) { System.out.println("Decoded file name: " + decodedName); } } } ``` 上述代码片段展示了如何将 URL 编码形式的字符串转化为实际可读取的文件名,并将其保存至目标位置[^2]。 #### 4. 动态命名策略优化 除了修复现有流程中的乱码现象外,还应考虑引入更灵活的动态命名机制来规避潜在风险。比如基于日期戳或其他唯一标识生成标准化文件名,减少对原始文件名依赖度的同时提升兼容性[^4]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值