在实际开发过程中,有时候用RestTemplate实现POST请求文件上传后端接口的功能,在本地Windows上自测都是没有问题的;但是部署到测试环境Linux服务器后,上传中文文件名就会出现异常。换用了Apache HttpComponents后就没问题,估计Spring的RestTemplate处理上传功能还有小bug。
pom文件加入相关jar包依赖:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.8</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.8</version>
</dependency>
代码如下:
MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest)httpServletRequest;
MultipartFile multipartFile = multipartHttpServletRequest.getFile("file");
Charset charset = StandardCharsets.UTF_8;
CharsetEncoder charsetEncoder = charset.newEncoder();
CharBuffer inputBuffer = CharBuffer.allocate(256);
inputBuffer.put(multipartFile.getOriginalFilename()).flip();
ByteBuffer outputBuffer = ByteBuffer.allocate(1024);
charsetEncoder.encode(inputBuffer, outputBuffer, true);
outputBuffer.flip();
String fileName = charset.decode(outputBuffer).toString();
File file = new File(fileName);
log.info("request upload url={} fileName={}", url, fileName);
try (FileOuputStream fos = new FileOuputStream(file)) {
fos.write(multipartFile.getBytes());
fos.flush();
} catch (IOException ex) {
log.error("request upload url={} fileName={} exception:", url, fileName, ex);
throw ex;
}
String result = "";
String boundary = "||";
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setCharset(charset);
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.setBoundary(boundary);
builder.addPart("file", new FileBody(file));
HttpEntity entity = builder.build();
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
if (response.getStatusLine().getStatusCode() == 200) {
log.info("upload url={} fileName={} succeed", url, fileName);
result = EntityUtils.toString(responseEntity, charset);
return result;
} else {
log.error("upload url={} fileName={} failed, status={}", url, fileName, response.getStatusLine().getStatusCode());
return null;
}
} catch(Exception ex) {
log.error("upload url={} fileName={} exception:", url, fileName, ex);
throw ex;
}