关于使用RestEasy 做上传文件,中文文件名称乱码问题。容器使用的是Undertow

发布时间 2023-11-09 09:43:44作者: 叶枫声
公司使用Resteasy做 REST 框架,web容器用的是Undertow

服务端上传文件相关代码

 1     @POST
 2     @Path("/normal/upload/{bizType}")
 3     @Consumes(MediaType.MULTIPART_FORM_DATA)
 4     public RpcResponse<List<FileDTO>> upload(@PathParam("bizType") String bizType, @Context HttpServletRequest request) {
 5         try {
 6             List<FileDTO> files = new LinkedList<>();
 7             for (Part part : request.getParts()) {
 8                 logger.debug("upload {} file:{}", part.getName(), part.getSubmittedFileName());
 9                 if (StringUtil.nonNullAndEmpty(part.getSubmittedFileName())) {
10                     AttachFilePO info = fileService.saveFile(CurrentContext.getTenantId(), bizType, "", part.getSubmittedFileName(),part.getSize(), part.getInputStream());
11 
12                     FileDTO dto = BeanCopier.copy(info, FileDTO.class);
13                     dto.setCdnPath(dto.getCdnPath().replace("${{real.domain.path}}", serverUrl));
14                     files.add(dto);
15                 }
16             }
17 
18             if (files.isEmpty()) {
19                 return new RpcResponse<>(BaseError.FILE_WRITE_FAILED.getCode(), "not found");
20             }
21             else {
22                 return new RpcResponse<List<FileDTO>>(files);
23             }
24         }
25         catch (Exception exp) {
26             Tuple.Pair<Integer, String> error = ParameterValidator.onException(exp);
27             return new RpcResponse<>(error.getFirst(), error.getSecond());
28         }
29     }

前端使用的是 form-data 方式进行的文件提交。但是运行过程中发现,非中文的文件上传正常。中文名称的文件则会出现乱码。

此处使用postman截图进行展示

服务端日志截图如下

 通过跟踪源码,发现处理类为  io.undertow.server.handlers.form.MultiPartParserDefinition.MultiPartUploadHandler

 1         private MultiPartUploadHandler(final HttpServerExchange exchange, final String boundary, final long maxIndividualFileSize, final long fileSizeThreshold, final String defaultEncoding) {
 2             this.exchange = exchange;
 3             this.maxIndividualFileSize = maxIndividualFileSize;
 4             this.defaultEncoding = defaultEncoding;
 5             this.fileSizeThreshold = fileSizeThreshold;
 6             this.data = new FormData(exchange.getConnection().getUndertowOptions().get(UndertowOptions.MAX_PARAMETERS, 1000));
 7             String charset = defaultEncoding;
 8             String contentType = exchange.getRequestHeaders().getFirst(Headers.CONTENT_TYPE);
 9             if (contentType != null) {
10                 String value = Headers.extractQuotedValueFromHeader(contentType, "charset");
11                 if (value != null) {
12                     charset = value;
13                 }
14             }
15            this.parser = MultipartParser.beginParse(exchange.getConnection().getByteBufferPool(), this, boundary.getBytes(StandardCharsets.US_ASCII), charset);
16 
17         }

Content-Type 为multipart/form-data;时,进入该类,代码种获取了charset 字符编码,由于没有显示声明编码,所以程序使用的时默认的 ISO-8859-1 编码。最终导致的乱码。

解决方法:在前端传文件前,手动设置 Content-Type 为 multipart/form-data;charset=utf8; 

搞定收工!!!