使用ByteArrayResource替换MultipartFile转换File实现RestTemplate文件上传

本文探讨了传统将MultipartFile转换为File进行文件上传可能导致服务器垃圾文件的问题,并提倡使用ByteArrayResource替代,以减少临时文件并提升性能。作者分享了转换思路和实例代码,帮助读者理解如何避免文件清理难题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

想必大家都会有通过 MultipartFile 接收前端的文件,然后后端通过 RestTemplate 实现文件上传。这里就涉及一个问题,可能小伙伴们看到网上大部分都是先将 MultipartFile 转换成 File ,然后再实现文件上传。其实我本人是不推荐这种实现方式的,因为这种方式可能会给服务器造成 “业务垃圾”,即有可能会在服务器上生成一些其它垃圾。因此,大家可以深入去看网上各种各样的转换。如下代码是我随便截图的:

// type1
File file = new File(Objects.requireNonNull(multipartFile.getOriginalFilename()));
FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);
FileSystemResource resource = new FileSystemResource(file);

//type2

if (!file.isEmpty()) {
    try {
              
          String filePath = "D:/upload/test/"+file.getOriginalFilename();
          System.out.println(filePath);
          File saveDir = new File(filePath);
          if (!saveDir.getParentFile().exists())
               saveDir.getParentFile().mkdirs();
           file.transferTo(saveDir);
           map.put("res","上传成功");
           return map;
} catch (Exception e) {
     e.printStackTrace();
    }
}

不管type1或type2等等,核心思想都是创建临时File文件,然后将MultipartFile转换成File临时文件,中间处理完业务,最后再删除File临时文件。

我采用这种方式,但是发现产生了一些其它的垃圾,如图所示:

 有些甚至是TMP结尾的垃圾文件,到时候我们操作删除,删除的只能是png文件。如果处理不当,可能删除文件失效,那么文件就会保留在服务器上。这不是我们想要的效果。

解决思路:

采用 ByteArrayResource ,至于它是啥,大家可以自行去学习。代码如下:

	@RequestMapping("/file")
	@ResponseBody
	public String testDemo(@RequestParam("uploadFile") MultipartFile file,StandardMultipartHttpServletRequest request) throws IOException {
		String url = "https://www.uploadFile.com/upload";
		RestTemplate template = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "multipart/form-data");
        headers.add("Content-Length",String.valueOf(file.getSize()));
        MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
        ByteArrayResource resource = new ByteArrayResource(file.getBytes()) {
            @Override
            public String getFilename() {
                return file.getOriginalFilename();
            }
        };
        parts.add("file",resource);
        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(parts, headers);
        ResponseEntity<String> responseEntity = template.postForEntity(url,httpEntity,String.class);
		return "Hello World!";
	}

其实文件的处理无非就是处理字节流。所以我就是从这个思路出发去换种方式实现想要的功能并且性能也比文件转换要更优。

<think>好的,我现在要解决用户的问题:使用RestTemplate上传文件时,中文文件名出现乱码的情况。用户提到在Spring环境下,如何解决这个问题。首先,我需要回忆一下RestTemplate的基本使用和可能涉及的编码问题。 首先,用户提到通过Zuul上传文件时,虽然微服务接收到的文件名没有乱码,但到了文件中心又出现乱码。这可能涉及多个环节的编码处理,比如请求的构建、传输过程中的编码设置,以及接收方的解码方式。需要逐步排查每个环节。 接下来,用户提供的引用内容中提到,在RestTemplate的doExecute方法中可能存在问题。这说明可能需要自定义RestTemplate的配置,特别是与HTTP请求相关的部分,比如消息转换器和编码设置。 首先,我应该考虑RestTemplate在发送请求时使用的默认编码。通常,默认的字符编码可能不是UTF-8,导致中文文件名在传输过程中变成乱码。需要检查MultipartFile上传时的Content-Type是否正确设置了charset=UTF-8。如果Content-Type没有正确指定编码,接收方可能无法正确解析文件名。 然后,引用[2]和[3]提到了解决方案,包括设置请求头、修改消息转换器以及处理字符串编码。例如,使用StringHttpMessageConverter时,默认的字符集可能不是UTF-8,需要显式设置为UTF-8。同时,在构建MultipartBody时,需要确保每个部分的Content-Disposition头正确包含filename*=UTF-8''这样的格式,以指定UTF-8编码。 可能的解决方案步骤包括: 1. 自定义RestTemplate的配置,替换默认的StringHttpMessageConverter,设置字符集为UTF-8。 2. 在构建MultiValueMap时,手动设置Content-Disposition头部,使用UTF-8编码的文件名。 3. 确保接收方的服务也正确支持UTF-8解码,可能需要检查接收方的处理逻辑,比如使用@RequestPart注解并配置字符集。 需要验证这些步骤是否覆盖了所有可能导致乱码的环节,比如请求头、消息转换器、多部分请求的编码等。同时,还要考虑是否需要在Zuul网关进行额外的编码配置,确保请求在通过网关时不会改变编码。 另外,可能需要处理文件名的URL编码,使用MimeUtility.encodeText()方法对文件名进行编码,确保特殊字符和中文字符被正确传输。这可以避免因特殊字符导致的解析错误或乱码。 最后,建议用户检查接收方的服务配置,比如是否设置了CharacterEncodingFilter,或者是否在application.properties中配置了spring.http.encoding.force-response=true等参数,确保整个请求链的编码一致。 总结起来,解决方案需要从RestTemplate的配置、多部分请求的构建、编码设置以及接收方的处理几个方面入手,确保每个环节都使用UTF-8编码,从而避免中文文件名乱码的问题。</think>### RestTemplate上传文件中文名乱码解决方案 #### 问题原因分析 1. **编码不匹配**:RestTemplate默认使用`ISO-8859-1`编码处理请求头,导致中文字符无法正确解析[^2]。 2. **多部分请求构建问题**:文件上传时若未显式指定`filename*`的UTF-8编码格式,接收方可能无法识别[^1]。 --- #### 解决方案步骤 ##### 1. 自定义RestTemplate配置 通过注入`RestTemplate`并替换默认的`StringHttpMessageConverter`,强制使用UTF-8编码: ```java @Bean public RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(); // 替换StringHttpMessageConverter为UTF-8 restTemplate.getMessageConverters().removeIf(c -> c instanceof StringHttpMessageConverter); restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8)); return restTemplate; } ``` ##### 2. 手动设置多部分请求编码 在构建文件上传请求时,**显式指定文件名编码**: ```java MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); body.add("file", new ByteArrayResource(file.getBytes()) { @Override public String getFilename() { // 使用RFC 5987规范编码文件名 return "filename*=UTF-8''" + URLEncoder.encode(originalFilename, StandardCharsets.UTF_8); } }); ``` ##### 3. 接收方统一解码 确保接收方服务配置UTF-8编码过滤器: ```java @Bean public FilterRegistrationBean<CharacterEncodingFilter> encodingFilter() { FilterRegistrationBean<CharacterEncodingFilter> bean = new FilterRegistrationBean<>(); bean.setFilter(new CharacterEncodingFilter("UTF-8", true)); return bean; } ``` --- #### 验证方法 1. **抓包检查请求头**:使用Wireshark或浏览器开发者工具,确认`Content-Disposition`头包含`filename*=UTF-8''`前缀。 2. **日志输出**:在接收方打印文件名,确认乱码已修复。 --- #### 扩展优化 - **全局编码配置**:在`application.properties`中添加: ```properties spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true spring.http.encoding.force=true ``` - **Zuul网关兼容**:若通过Zuul代理,需同步配置Zuul的编码过滤器。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值