背景:现有Springboot微服务A,其对外提供一个多文件上传的接口,接口代码如下:
/**
* 远程服务提供的多文件上传的REST API
* @param files
* @param request
* @return
*/
@RequestMapping(value = "/file/upload", method = RequestMethod.POST)
public String uploadFile(@RequestParam("files") MultipartFile[] files, HttpServletRequest request) {
if (ArrayUtils.isEmpty(files)) {
logger.info("No file provided------");
ret.put("status", CommonConstant.RES_FAILURE);
ret.put("errorMsg", "请至少选择一个文件上传!");
return ret.toJSONString();
}
// TODO 具体略
}
现在,我在Springboot微服务B中,需要调用服务A的文件上传接口,这里演示使用RestTemplate完成服务间的调用。参考代码如下:
/**
* 使用RestTemplate完成多文件上传
* @param files
* @param request
* @return
*/
public String uploadFile(MultipartFile[] files, HttpServletRequest request) {
String tempPath = "E:\data\test\app\document";
String uploadUrl = "http://localhost:9066/api/v1/file/upload";
// 获取请求参数
String type = request.getParameter("type");
String id = request.getParameter("id");
String ptnReference = request.getParameter("ptnReference");
String chineseName = request.getParameter("chineseName");
logger.info("Type is [{}], id is [{}], ptnRef is [{}], chineseName is [{}]----", type, id, ptnReference,
chineseName);
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("multipart/form-data;charset=UTF-8"));
MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
List<String> tempList = new ArrayList<>(); // 保存临时文件
for (MultipartFile file : files) {
createDir(tempPath);
String tempFilePath = tempPath + file.getOriginalFilename();
try {
// create local temp file
FileCopyUtils.copy(file.getInputStream(), new FileOutputStream(tempFilePath));
tempList.add(tempFilePath);
// MultipartFile 直接转 FileSystemResource是不行的
FileSystemResource resource = new FileSystemResource(tempFilePath); // 把临时文件变成FileSystemResource
// LinkedMultiValueMap中,key对应的value值其实是一个LinkedList,所以可以一直往同一个key中add值,不会覆盖
param.add("files", resource);
} catch (Exception e) {
logger.error("保存文件{}至本地临时文件异常!", file.getOriginalFilename(), e);
}
}
param.add("id", id);
param.add("type", type);
param.add("ptnReference", ptnReference);
param.add("chineseName", chineseName);
// 发送请求,这里的restTemplate是通过@Autowired注入的
HttpEntity<MultiValueMap<String, Object>> formEntity = new HttpEntity<>(param, headers);
String result = restTemplate.postForObject(uploadUrl, formEntity, String.class);
logger.info("ptnReference==[{}]的交易, 文件上传的结果===={}", ptnReference, result);
// delete local temp file
deleteLocalTempFiles(tempList);
return result;
}
private void deleteLocalTempFiles(List<String> tempList) {
if (!CollectionUtils.isEmpty(tempList)) {
for (String fileName : tempList) {
new File(fileName).delete();
}
}
}
private void createDir(String tempPath) {
File file = new File(tempPath);
if (!file.exists()) {
file.mkdirs();
}
}
主要思路就是,现将文件转化为FileSystemResource,然后通过LinkedMultiValueMap来传递参数。
参考文档:https://www.baeldung.com/spring-rest-template-multipart-upload