使用restTemplate上传图片

本文分享了使用restTemplate上传图片到微信服务器的实践经验,解决了因缺少filename参数导致的file为空错误,详细介绍了如何构造请求头、body及multipart-form-data格式。

网上有很多restTemplate上传图片的例子,但是我遇到的坑,却没有解决办法,于是在墙外面找到了解决方案,现分享如下

上送给微信的请求报文必须如上(事实证明少一个filename微信都提示你file不能为空)这个提示误导两个小时排查问题

代码摘要如下:

private ResultModel httpRequestWechatUploadImage(String url,String head,String body,String imageUrl,String imageName){
        try{
            //构造请求头
            HttpHeaders headers = new HttpHeaders();
            headers.add("Authorization", head);
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);

            ResponseEntity<String> responseEntity;

            //构建第一个boundary
            HttpHeaders metaHeader = new HttpHeaders();
            metaHeader.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<String> jsonHttpEntity = new HttpEntity<>(body, metaHeader);

            //构建第二个boundary
            HttpHeaders pictureHeader = new HttpHeaders();
            pictureHeader.setContentType(MediaType.IMAGE_JPEG);
            //不设置此contentDisposition则会报file必填
            pictureHeader.setContentDispositionFormData("file",imageName);
            ByteArrayResource bar = new ByteArrayResource(CommonUtils.getByteFromURL(imageUrl));
            HttpEntity<ByteArrayResource> picturePart = new HttpEntity<>(bar, pictureHeader);

            //组成body
            MultiValueMap<String, Object> multipartRequest = new LinkedMultiValueMap<>();
            multipartRequest.add("meta", jsonHttpEntity);
            multipartRequest.add("file", picturePart);

            //放body 和 head
            HttpEntity entity = new HttpEntity(multipartRequest, headers);
            //请求微信
            responseEntity = restTemplate().exchange(url,HttpMethod.POST,entity,String.class);
            if(responseEntity.getStatusCode() == HttpStatus.OK){
                return new ResultModel(true, responseEntity.getBody());
            }else{
                return new ResultModel(false, responseEntity.toString());
            }
        } catch(RestClientResponseException ex){
            System.out.println("rest client exception,body"+ex.getResponseBodyAsString());
            ex.printStackTrace();
            return new ResultModel(false,ex.getResponseBodyAsString());
        } catch (Exception e){
            System.out.println("exception "+e.getMessage());
            e.printStackTrace();
        }
        return new ResultModel(false,"request wechat system error");
    }

 

<think>嗯,用户的问题是关于使用RestTemplate和FileSystemResource上传图片时出现中文乱码的解决方案。用户提供了三个相关引用,其中引用[3]特别提到了设置multipart/form-data的Content-Type,但没有明确涉及中文乱码的处理。 用户的核心诉求很明确:解决上传图片时文件名或内容出现乱码的问题。根据经验,这类问题通常源于字符编码不一致。需要从三个关键点切入: 首先是请求头编码设置,引用[3]设置了"charset=UTF-8"但位置可能不正确,multipart请求的字符集应该定义在boundary参数里; 其次是文件名编码,FileSystemResource默认使用系统编码,如果文件名含中文而服务器使用UTF-8就可能乱码; 最后是服务器端解码方式,需要确认服务器是否支持UTF-8。 解决方案应该分步骤: 第一强化请求头设置,采用RFC规范的标准写法; 第二主动指定文件名编码,覆盖系统默认值; 第三添加全局字符集配置确保请求处理链统一。用户可能已经尝试过基础方案但未生效,需要更彻底的UTF-8强制策略。 还要考虑用户环境差异,比如Windows系统默认GBK编码的情况。补充建议检查服务器日志能帮助定位问题端,因为乱码可能是单端或双端不一致导致。最后推荐的UTF-8配置属于防御性编程策略,能从根本上避免此类问题。 </think>使用RestTemplate上传图片出现中文乱码问题,通常是由于字符编码不一致导致的。以下是完整的解决方案和步骤: ### 🔧 一、核心解决方案 1. **强制指定请求编码格式** 在`HttpHeaders`中显式设置UTF-8字符集: ```java HttpHeaders headers = new HttpHeaders(); // 关键:使用RFC规范的正确格式声明UTF-8 MediaType mediaType = MediaType.parseMediaType("multipart/form-data; charset=UTF-8"); headers.setContentType(mediaType); ``` 2. **文件名编码处理** `FileSystemResource`默认使用系统编码,需手动指定UTF-8: ```java String encodedFileName = URLEncoder.encode(file.getName(), StandardCharsets.UTF_8); FileSystemResource resource = new FileSystemResource(file) { @Override public String getFilename() { return encodedFileName; // 重写文件名方法 } }; ``` ### 🛠 二、完整上传代码示例 ```java public String uploadImage(String url, File file) throws UnsupportedEncodingException { // 1. 文件名UTF-8编码 String encodedName = URLEncoder.encode(file.getName(), "UTF-8"); // 2. 创建带编码的文件资源 FileSystemResource resource = new FileSystemResource(file) { @Override public String getFilename() { return encodedName; } }; // 3. 设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.parseMediaType("multipart/form-data; charset=UTF-8")); // ✅关键设置 // 4. 构建请求体 MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); body.add("file", resource); // 字段名需与服务器一致 body.add("comment", "带中文的参数"); // 普通参数同样支持中文 // 5. 发送请求 RestTemplate restTemplate = new RestTemplate(); ResponseEntity<String> response = restTemplate.postForEntity( url, new HttpEntity<>(body, headers), String.class ); return response.getBody(); } ``` ### ⚠ 三、注意事项 1. **全局编码配置**(推荐) 在Spring Boot配置文件中强制UTF-8编码: ```yaml spring: http: encoding: force: true # 强制所有请求使用UTF-8 charset: UTF-8 ``` 2. **服务器端验证** 确保服务器接口已配置UTF-8解码: ```java // Spring MVC示例 @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity<?> handleUpload( @RequestPart("file") MultipartFile file, @RequestParam String comment // 接收中文参数 ) { // 需检查服务器配置文件编码 } ``` 3. **日志诊断** 在客户端启用请求日志验证编码: ```java restTemplate.setInterceptors(Collections.singletonList(new ClientHttpRequestInterceptor() { @Override public ClientHttpResponse intercept(HttpRequest req, byte[] body, ClientHttpRequestExecution ex) { System.out.println("Headers: " + req.getHeaders()); // 检查Content-Type return ex.execute(req, body); } })); ``` ### 💡 技术原理 乱码通常由三端编码不一致引起: 1. **客户端请求头**未声明UTF-8(默认ISO-8859-1) 2. **文件名字节传输**未显式编码(中文操作系统默认GBK) 3. **服务器解析**未使用UTF-8解码 > 📌 通过强制UTF-8三端统一即可解决:客户端编码 → 传输声明 → 服务器解码[^1][^3] --- ### ❓相关问题 1. RestTemplate如何实现多文件上传并保证中文文件名正确? 2. Spring Boot中如何全局配置RestTemplate的字符编码? 3. 使用MultipartFile接收文件时服务器端如何避免中文乱码? 4. RestTemplate与大文件上传时有哪些优化方案? [^1]: RestTemplate文件上传基础方法 [^3]: 请求头字符集设置示例
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值