前因后果(不想看的可以直接看分界线之间的内容):

做一个项目, 前端类似这种按钮:

restemplate 返回body包含NUL 如何去掉NUL resttemplate 返回值_上传

Html代码:

<form action="http://172.22.25.235:8004/storage/uploadFile/" method="post" enctype="multipart/form-data">
    <p> 选择文件: <input type="file" name="file"/></p>
    <p><input type="submit" value="提交"/></p>
</form>

即,将你选中的文件 发送到指定 网址。 这个文件是可以直接就上传成功的。

但我的任务 就要我来插一脚

因为我要得到这个文件的 名称、日期 、啥啥啥的各种属性,所以 上传的时候 需要先到后端让我 记录各种数据,(也就是说将这个文件的这种属性记录并保存到数据库中以后好根据这些数据 再下载这个文件)

,再上传,这一脚 插得 我真的学到好多东西。

所以 ,这个按钮HTML 就变成了   即 接口变成了 localhost://xxxx/fileupload     这个“中间商”了

<form action="fileUpload" method="post" enctype="multipart/form-data">
    <p> 选择文件: <input type="file" name="fileName"/></p>
    <p><input type="submit" value="提交"/></p>
</form>

然后 后端 再将文件 发送到 开始那个网址的  接口 http://172.22.25.235:8004/storage/uploadFile/+fileName


正文:                                  直接上代码

@RequestMapping("fileUpload")
    @ResponseBody
    //还要加个返回 responseBody
    //因为multipartfile 不能得到他的路径,所以需要生成临时文件再 转换 Object类型 再上传
    public String fileUpload(@RequestParam("fileName") MultipartFile file) throws IOException {
        if (file.isEmpty()) {
            return "false";
        }
        String fileName = file.getOriginalFilename();//name
        String tempFilePath = System.getProperty("java.io.tmpdir") + file.getOriginalFilename();
        File tempFile = new File(tempFilePath);
        file.transferTo(tempFile);//生成临时文件

        // 获取文件属性(还要额外形参这里就不给出了) 一系列的存表 操作
        String url = "http://172.22.25.235:8004/storage/uploadFile/";
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.add("Accept",MediaType.APPLICATION_JSON.toString());
        headers.setContentType(MediaType.parseMediaType("multipart/form-data;charset=UTF-8"));
        MultiValueMap<String,Object> param = new LinkedMultiValueMap<>();

        //MultipartFile 直接转 fileSystemResource 是不行的
        FileSystemResource resource = new FileSystemResource(tempFilePath);//把临时文件变成filesystemresource
        
        param.add("file",resource);

        HttpEntity<MultiValueMap<String,Object>> formEntity = new HttpEntity<>(param,headers);
        ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url,formEntity, JSONObject.class);
        JSONObject jsonObject =responseEntity.getBody();
        System.out.println(jsonObject.get("data"));
//        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url,formEntity, String.class);
//        String body = responseEntity.getBody();

        tempFile.delete();//删除临时文件文件
        return jsonObject.toString();
    }

坑点:

1: MultipartFile 是 前端 <input type="file" ....> 按钮发送的固定类型, 所以后端 接收时 只能用这个类型接收,

但是  用 restTemplate  发送 post 请求时,需要用Map 来封装 请求体(http基础不好,我这么叫它) 如上面的  formEntity ,并且请求体里面的 “file” 属性 要是 FileSystemResource 类型的 ,而不能是 MultipartFile 类型,这就涉及到第二个坑点

2MultipartFile 直接转化为 FileSystemResource 类型 是行不通的,因为 FileSystemResource 需要根据文件路劲 来构造,

但multipartFile 对象 没有路径属性,(也就是说从前端选择文件后,点击发送按钮之后,这个文件就只有内容了,没有了他的地址了) 那怎么办? 这个时候就是知识点了—— java 是有临时文件路径的 (windows 一般是在c/user/xxx/AppData/temp 里面 linux 是/tmp 文件夹)  获取方法:System.getProperty("java.io.tmpdir")        返回的是临时目录的路径

可能聪明的童靴已经想到了,我们可以在这个临时目录里生成一个临时文件  ,内容就是 那个MultipartFile 的内容的复制,然后这个临时文件的路径是知道的,那么 multipartfile 也就得到了,restTemplate.postForEntity 就能发送成功了

最后 postForEntity  函数的第二个参数 的设置也要  添加一些编码啥的设置 才行,如上面的 FormEntity 的设置,如果不设置的话很可能不成功,我看别的博客直接  String string = rest.postForObject(url, param, String.class); 这样不是整个请求体,缺少必要的编码设置之类的应该成功不了的

哦,对了,我上面 是想直接得到 json 类型的返回值,好取出其中的“data”属性,其实ResponseEntity<xxx>可以设置你想要的返回类型的 如 可以填 String   多余不说了,一切都在代码中……


最后附上结果  点击发送按钮并返回:

restemplate 返回body包含NUL 如何去掉NUL resttemplate 返回值_MultipartFile_02

restemplate 返回body包含NUL 如何去掉NUL resttemplate 返回值_RestTemplate_03

后台:

restemplate 返回body包含NUL 如何去掉NUL resttemplate 返回值_MultipartFile_04

到时候就利用这串 东西 去下载 对应文件