xChar

上传多个文件

上传时,在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);
}

通过byte[]上传文件

有时,上传文件的数据源并不是来自于系统,不能使用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复制过来的类

Loading comments...