RestTemplate在Linux上传multipart文件出现CTRL-CHAR code13错误如何解决?
问题原因
错误提示中的CTRL-CHAR, code 13对应的是ASCII回车符\r,该问题由Windows和Linux系统的换行符差异导致:
- Windows系统默认换行符为
\r\n(回车+换行),Linux系统默认换行符为\n(仅换行) - 代码在Windows环境运行时,RestTemplate生成的multipart请求报文、携带的文件元数据都使用Windows默认换行符,和服务端解析逻辑兼容,因此运行正常
- 部署到Linux环境后,要么RestTemplate生成的multipart报文使用了Linux默认换行符、不兼容服务端的解析规则,导致服务端返回格式畸形的JSON;要么服务端返回的JSON中携带了未转义的
\r控制字符,Jackson默认配置下不允许未转义的控制字符出现在JSON字符串中,直接抛出解析异常
解决方案
你可以根据自己的业务场景选择以下任意一种方案修复:
方案1:强制multipart请求使用统一换行符
自定义FormHttpMessageConverter,强制指定multipart报文的换行符为标准的\r\n,和Windows环境逻辑对齐,兼容绝大多数服务端的解析逻辑:
// 自定义FormHttpMessageConverter FormHttpMessageConverter formConverter = new FormHttpMessageConverter(); // 强制使用\r\n作为换行符 formConverter.setLineSeparator("\r\n"); // 把自定义转换器添加到RestTemplate的转换器列表最前面,优先生效 restTemplate.getMessageConverters().add(0, formConverter);
方案2:开启Jackson控制字符解析支持
修改Jackson反序列化配置,允许JSON中存在未转义的控制字符,跳过响应解析报错:
MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(); ObjectMapper objectMapper = new ObjectMapper(); // 开启允许未转义控制字符的特性 objectMapper.configure(DeserializationFeature.ALLOW_UNQUOTED_CONTROL_CHARS, true); jacksonConverter.setObjectMapper(objectMapper); // 替换RestTemplate中原有的Jackson转换器 restTemplate.getMessageConverters().removeIf(converter -> converter instanceof MappingJackson2HttpMessageConverter); restTemplate.getMessageConverters().add(jacksonConverter);
方案3:清理文件名中的特殊控制字符
如果问题是由文件名携带\r等控制字符导致,可以自定义FileSystemResource子类,重写文件名获取逻辑,清理特殊字符:
public class CleanedFileSystemResource extends FileSystemResource { public CleanedFileSystemResource(File file) { super(file); } @Override public String getFilename() { // 移除文件名中的所有控制字符 return super.getFilename().replaceAll("\\p{Cntrl}", ""); } }
上传文件时使用自定义的CleanedFileSystemResource代替原生的FileSystemResource即可:
form.add("image", new CleanedFileSystemResource(imageFile));
内容的提问来源于stack exchange,提问作者Adefisola Adigun
相关产品推荐
相关产品推荐

