RestTemplate模拟HTTP-POST请求发送文件

今天项目上碰到一个比较不常用的需求,即业务子系统之间通过接口传递文件的功能,起初想到的上传的都是图片,可以直接转Base64字符串,直接通过POST传递过去就可以了,但是本着负责的原则,别后期挖坑,还是又通过其他的方式实现的,方式就是通过RestTemplate的postForEntity方法实现文件的POST请求发送

发送端

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public static String sendRestTempPost(String url, Map<String,Object> paramsMap, MultipartFile file) throws Exception{

//创建一个RestTemplate对象
RestTemplate restTemplate =new RestTemplate();
//MultiValueMap里面,用作发送文件
MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();

//1. 首先将字符串等类型的参数放入参数对象中
if (!paramsMap.isEmpty()) {
for (Map.Entry<String, Object> entries : paramsMap.entrySet()) {
params.add(entries.getKey(), entries.getValue());
}
}

File tempFile = null;
//2.处理文件
if(!file.isEmpty()){
String tempFilePath = System.getProperty("java.io.tmpdir") + file.getOriginalFilename();
tempFile = new File(tempFilePath);
//生成临时文件
file.transferTo(tempFile);

// 文件必须封装成FileSystemResource这个类型后端才能收到附件
FileSystemResource resource = new FileSystemResource(tempFilePath);
params.add("file",resource);
}

// 调用接口即可
ResponseEntity<String> responseStr = restTemplate.postForEntity(url, params, String.class);
//如果文件存在的话,进行删除操作
if(tempFile!= null && tempFile.exists()){
tempFile.delete();
}
//根据自己需求判断statuscode等相关字段,这里只是简单的实现,所以直接拿了body的内容返回
return responseStr.getBody();
}

解析

  1. 这里使用MultiValueMap而不是常规Map的原因应该是显而易见的,常规的Map应该是无法满足存放java.io.File类型的文件的能力吧,这里只是猜测
  2. 接下来是传递的参数进行了遍历,遍历从调用的方法传递过来的参数,然后组装到MultiValueMap
  3. 判断传递过来的文件是不是空的,如果不是空的,进行如下处理
    • 首先创建一个临时文件,当然如果你在当前服务器已经保存过文件,那就更好不过了,直接读取过来,就可以操作了
    • 然后将文件封装成FileSystemResource对象,这个是必须得封装的,不封装的话是没法传递过去的
    • 将文件放入到MultiValueMap
  4. 调用接口进行文件及相关参数的发送操作
  5. 最后还需要判断文件不为空的时候的删除操作

阶段总结

这个地方发现了一个问题和一个优化的点:

  1. 问题是传递过去如果不带header的时候会出现传递的参数汉字会乱码的问题
  2. 优化的点是如果一次性发送多个文件的时候,该如何去做处理(这个地方尝试了一下,结果一直报错,后续再试试)

接收端

代码

1
public JSONObject upLoadImg(String _userId,String applid,String doc_code,String file_type,String file_path,String file_id,String file_name,MultipartFile file)

解析

接收端相信我写到这里,下面的应该都会吧,能拿到MultipartFile剩下的都不是问题了,直接从文件读取流,根据路径和文件名输出到硬盘路径就可以了

补充

下面补充下MultipartFile文件转成流并保存的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* @param file //文件对象
* @param filePath //上传路径
* @param fileName //文件名
* @return 文件名
*/
public static String fileUp(MultipartFile file, String filePath, String fileName){
String extName = ""; // 扩展名格式:
try {
if (file.getOriginalFilename().lastIndexOf(".") >= 0){
extName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
}
copyFile(file.getInputStream(), filePath, fileName+extName).replaceAll("-", "");
} catch (IOException e) {
e.printStackTrace();
System.out.println(e);
}
return fileName+extName;
}

/**
* 写文件到当前目录的upload目录中
*
* @param in
* @throws IOException
*/
private static String copyFile(InputStream in, String dir, String realName)
throws IOException {
File file = new File(dir, realName);
if (!file.exists()) {
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
file.createNewFile();
}
FileUtils.copyInputStreamToFile(in, file);
return realName;
}

0%