URLDecoder解码丢失加号问题:求保留加号的解码方案
解决URLDecoder解码时加号被替换为空格的问题
当文件名abc你好+在Content-Disposition头中被编码为abc%E4%BD%A0%E5%A5%BD+时,用java.net.URLDecoder.decode()解码会把加号替换成空格,导致结果和原文件名不符。下面提供几种解决方法,既能解码百分号编码,又能保留加号:
方法一:手动处理(无需第三方包)
URLDecoder的解码逻辑遵循application/x-www-form-urlencoded规范,默认会把加号转成空格。要保留加号,有两种简单的手动处理方式:
方式1:预处理替换加号
解码前先把字符串中的+替换成它的百分号编码形式%2B,再用URLDecoder解码:
import java.net.URLDecoder; import java.nio.charset.StandardCharsets; public class FileNameDecodeExample { public static void main(String[] args) { String encodedFileName = "abc%E4%BD%A0%E5%A5%BD+"; // 先将+替换为%2B String preprocessed = encodedFileName.replace("+", "%2B"); String decoded = URLDecoder.decode(preprocessed, StandardCharsets.UTF_8.name()); System.out.println(decoded); // 输出: abc你好+ } }
方式2:自定义百分号解码逻辑
自己实现只处理%XX格式编码的方法,直接忽略加号,保留原字符:
import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; public class CustomDecoder { public static String decodePercentOnly(String encoded, Charset charset) { StringBuilder result = new StringBuilder(); int len = encoded.length(); int i = 0; while (i < len) { char c = encoded.charAt(i); if (c == '%' && i + 2 < len) { // 解析%XX格式的十六进制编码 String hex = encoded.substring(i + 1, i + 3); try { byte[] byteArr = {(byte) Integer.parseInt(hex, 16)}; result.append(new String(byteArr, charset)); i += 3; } catch (NumberFormatException e) { // 无效的百分号编码,直接保留原字符 result.append(c); i++; } } else { // 非百分号编码字符,直接追加 result.append(c); i++; } } return result.toString(); } public static void main(String[] args) { String encodedFileName = "abc%E4%BD%A0%E5%A5%BD+"; String decoded = decodePercentOnly(encodedFileName, StandardCharsets.UTF_8); System.out.println(decoded); // 输出: abc你好+ } }
方法二:使用第三方库(Apache Commons Codec)
Apache Commons Codec库的URLCodec提供了更灵活的解码控制,可以关闭加号替换为空格的行为:
代码示例
import org.apache.commons.codec.net.URLCodec; import java.nio.charset.StandardCharsets; public class CommonsCodecExample { public static void main(String[] args) throws Exception { URLCodec codec = new URLCodec(); // 设置解码时不将+替换为空格 codec.setEncodeChar('+'); String encodedFileName = "abc%E4%BD%A0%E5%A5%BD+"; String decoded = codec.decode(encodedFileName, StandardCharsets.UTF_8.name()); System.out.println(decoded); // 输出: abc你好+ } }
依赖引入(Maven)
如果用Maven管理项目,需要在pom.xml中添加依赖:
<dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.15</version> <!-- 建议使用最新稳定版本 --> </dependency>
内容的提问来源于stack exchange,提问作者varen
相关产品推荐
相关产品推荐

