Undertow FileUtil读取UTF-8字符截断问题的最优方案咨询
问题:Undertow Multipart临时文件读取导致UTF-8乱码
当multipart请求大小超过MultipartConfigElement.fileSizeThreshold时,请求内容会被写入临时文件。Undertow的FileUtils类通过以下代码读取该文件:
public static String readFile(InputStream file, Charset charSet) { try (BufferedInputStream stream = new BufferedInputStream(file)) { byte[] buff = new byte[1024]; StringBuilder builder = new StringBuilder(); int read; while ((read = stream.read(buff)) != -1) { builder.append(new String(buff, 0, read, charSet)); } return builder.toString(); } catch (IOException e) { throw new RuntimeException(e); } }
这段代码存在核心问题:UTF-8非英文字符(如匈牙利语中的á)由多字节组成,当缓冲区刚好截断这些字节片段时,每次将部分字节直接转换为字符串会生成无效字符,最终拼接出乱码。例如原字符串támogatás会变成támogat��s,其中完整的á被拆分为两个乱码字符。
解决方案分析与最优选择
可选方案评估
- 增大阈值大小:仅能临时规避问题,当请求大小突破新阈值时,乱码问题会再次出现,无法从根源解决。
- 避免使用multipart:业务场景中通常无法绕过multipart请求,可行性极低。
- 提交Undertow Jira工单:从框架层面修复bug,是彻底解决问题的最优方案。
具体处理建议
- 提交官方工单:向Undertow官方Jira提交bug报告,附上问题代码、复现步骤和乱码示例,建议官方改用字符流读取方式替代字节流拆分转换。修复后的参考代码可以是:
public static String readFile(InputStream file, Charset charSet) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(file, charSet))) { StringBuilder builder = new StringBuilder(); char[] charBuff = new char[1024]; int read; while ((read = reader.read(charBuff)) != -1) { builder.append(charBuff, 0, read); } return builder.toString(); } catch (IOException e) { throw new RuntimeException(e); } }
该方式通过InputStreamReader直接按字符读取,从根本上避免了多字节字符被截断的问题。
- 临时应急修复:若需立即解决问题,可在项目中自定义
FileUtils类覆盖Undertow的实现,或通过请求拦截器重新处理multipart临时文件的读取逻辑,确保采用字符流完整读取内容。
内容的提问来源于stack exchange,提问作者László Tóth
相关产品推荐
相关产品推荐

