上传时,在MultiValueMap对象中的同一个key中添加多个value,传递时会封装成数组
key=[value1, value2, value3]
接收端
@PostMapping(value = "/fileVerify/verifyFileBatch", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Result verifyFileBatch(@RequestPart(value = "files") MultipartFile[] files){
log.info("批量文件验证...");
return Result.success();
}
请求端
/**
* 测试:请求多文件验证
*/
@Test
public void requestVerifyBatchTest(){
String url = "http://192.168.200.163:8080/fileVerify/verifyFileBatch";
// 组装header
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
// 组装文件
MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
// file1, 加密后的文件1
String filePath1 = getClass().getResource("/1684290580318.file").getPath();
File file1 = new File(filePath1);
FileSystemResource resource1 = new FileSystemResource(file1);
// file2, 加密后的文件2
String filePath2 = getClass().getResource("/1684290580318-2.file").getPath();
File file2 = new File(filePath2);
FileSystemResource resource2 = new FileSystemResource(file2);
// 添加到表单
form.add("files", resource1);
form.add("files", resource2);
// 发送请求
HttpEntity<MultiValueMap> requestEntity = new HttpEntity(form, headers);
ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, requestEntity, String.class);
// 返回的是密文
log.info("responseEntity={}", responseEntity);
}
有时,上传文件的数据源并不是来自于系统,不能使用FileSystemResource去调用文件上传接口
字节源依旧可以作为上传源
@HystrixCommand(commandKey = "sysInfoUploadCommand", threadPoolKey = "sysInfoUploadThreadPool",
fallbackMethod = "sysInfoUploadFallBack", commandProperties = {
@HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS, value = "6000"),
@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, value = "30"),
@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, value = "60"),
@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value = "10000")
})
public YzyUploadRsp sysInfoUpload(String fileName, byte[] fileBytes, String token){
MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
ByteArrayResource fileAsResource = new ByteArrayResource(fileBytes) {
@Override
public String getFilename() {
// return new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.US_ASCII);
return fileName;
}
@Override
public long contentLength() {
return fileBytes.length;
}
};
form.add("type", "file");
form.add("file", fileAsResource);
form.add("fileName", fileName);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.set("Accept-Charset", StandardCharsets.UTF_8.toString());
headers.add("Keep-Alive", "timeout=60, max=1000");
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
headers.add("authorization", token);
headers.add("ref-secret-key", refSecretKey);
headers.add("Content-Disposition", "attachment; filename=" + fileName);
String url = yjzServerDomain + yzyUploadUri;
log.info("请求上传文件, url={}", url);
HttpEntity<MultiValueMap> requestEntity = new HttpEntity(form, headers);
ResponseEntity<UploadRsp> responseEntity =
uploadRestTemplate.postForEntity(url, requestEntity, UploadRsp.class);
// restTemplate.postForEntity(url, requestEntity, UploadRsp.class);
log.info("上传文件结果: {}", responseEntity);
return Optional.of(responseEntity)
.filter(entity -> entity.getStatusCode().is2xxSuccessful())
.map(entity -> entity.getBody())
.orElseThrow(() -> new BussJsonException("上传文件失败"));
}
在低版本spring cloud(1.x)中上传文件时,对文件名使用了硬编码"US-ASCII"
org.springframework.http.converter.FormHttpMessageConverter#getAsciiBytes(String name)
解决方法为,复制该类,修改编码方式后,手动添加到restTemplate解析器中
@Bean("uploadRestTemplate")
public RestTemplate uploadRest(){
// FormHttpMessageConverter在设置Part-Header编码时,使用了硬编码 US-ASCII,导致中文乱码
// see: FormHttpMessageConverter#getAsciiBytes
MyFormHttpMessageConverter fc = new MyFormHttpMessageConverter();
List<HttpMessageConverter<?>> partConverters = new ArrayList<>();
partConverters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
partConverters.add(new ResourceHttpMessageConverter());
// fc.setMultipartCharset(StandardCharsets.UTF_8);
fc.setPartConverters(partConverters);
RestTemplate restTemplate = new RestTemplate(new HttpsClientRequestFactory());
restTemplate.setMessageConverters(Arrays.asList(fc, new MappingJackson2HttpMessageConverter()));
return restTemplate;
}
其中,MyFormHttpMessageConverter是从FormHttpMessageConverter复制过来的类