【问题标题】:File upload of CommonsMultipartFile using RestTemplate is failing使用 RestTemplate 上传 CommonsMultipartFile 的文件失败
【发布时间】:2018-09-19 04:52:57
【问题描述】:

我正在尝试使用在请求中接受 CommonsMultipartFile 的 Web 服务。因此,我使用 Spring 的 RestTemplate 创建了一个 HTTP 客户端。下面是接受 URI 和 MultipartFile 作为参数的方法。我正在尝试以 ByteArrayResource 的形式将此文件传递给 Web 服务。

public String upload(String uri, MultipartFile file) throws IOException {
    logger.info("URI: " + uri);

    ByteArrayResource fileAsResource = new ByteArrayResource(file.getBytes()) {
        @Override
        public String getFilename() {
            return file.getOriginalFilename();
        }
    };

    MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
    parts.add("file", fileAsResource);
    parts.add("fileName", file.getOriginalFilename());

    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);

    HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(parts, httpHeaders);

    ResponseEntity<String> responseEntity = rest.exchange(uri, HttpMethod.POST, requestEntity, String.class);

    this.setStatus(responseEntity.getStatusCode());
    return responseEntity.getBody();
}

这就是我创建 CommonsMultipartFile 的方式:

private MultipartFile getCommonsMultipartFile() throws FileNotFoundException, IOException {
    File file = new File("C:\\Dummy_Test.txt");

    DiskFileItemFactory factory = new DiskFileItemFactory();
    FileItem fileItem = factory.createItem( "file", "multipart/form-data", false, "Dummy_Test.txt" );
    IOUtils.copy(new FileInputStream(file), fileItem.getOutputStream());
    MultipartFile commonsMultipartFile = new CommonsMultipartFile(fileItem);

    return commonsMultipartFile;
}

但是,每当我运行此客户端以访问 Web 服务时,我都会不断收到此错误。

 org.springframework.web.client.ResourceAccessException: I/O error: resource loaded from byte array cannot be resolved to absolute file path; nested exception is java.io.FileNotFoundException: resource loaded from byte array cannot be resolved to absolute file path
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:453)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:401)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:377)
    at com.attikala.service.UploaderService.upload(UploaderService.java:118)
    at com.attikala.service.UploaderService.main(UploaderService.java:55)
Caused by: java.io.FileNotFoundException: resource loaded from byte array cannot be resolved to absolute file path
    at org.springframework.core.io.AbstractResource.getFile(AbstractResource.java:107)
    at org.springframework.core.io.AbstractResource.contentLength(AbstractResource.java:116)
    at org.springframework.http.converter.ResourceHttpMessageConverter.getContentLength(ResourceHttpMessageConverter.java:99)
    at org.springframework.http.converter.ResourceHttpMessageConverter.write(ResourceHttpMessageConverter.java:81)
    at org.springframework.http.converter.ResourceHttpMessageConverter.write(ResourceHttpMessageConverter.java:1)
    at org.springframework.http.converter.FormHttpMessageConverter.writePart(FormHttpMessageConverter.java:288)
    at org.springframework.http.converter.FormHttpMessageConverter.writeParts(FormHttpMessageConverter.java:252)
    at org.springframework.http.converter.FormHttpMessageConverter.writeMultipart(FormHttpMessageConverter.java:242)
    at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:194)
    at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:1)
    at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:588)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:436)
    ... 4 more

有人可以帮我弄清楚这里发生了什么吗?

注意:如果我使用下面的代码上传文件,它工作得很好。

public String upload(String uri) {
    LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();

    FileSystemResource value = new FileSystemResource(new File("C:\\Dummy_Test.txt"));
    map.add("file", value);
    map.add("fileName", "Dummy_Test.txt");

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.MULTIPART_FORM_DATA);

    HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);

    RestTemplate restTemplate = new RestTemplate();
    ResponseEntity<String> responseEntity = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, String.class);

    return responseEntity.getBody();
}

所以,我在想,我是否需要始终为我上传的文件提供绝对路径?我知道我在这里遗漏了一些东西。不知道是什么。

谢谢。

【问题讨论】:

    标签: java file web-services file-upload multipartform-data


    【解决方案1】:

    最后,我发现了发生了什么。 我来了 -

    当这个语句

    ResponseEntity<String> responseEntity = rest.exchange(uri, HttpMethod.POST, requestEntity, String.class);
    

    被执行,在幕后它试图从传递的 MultipartFile 中提取java.io.File 类型的文件,然后获取文件长度。但是 MultipartFile 不是那种类型,因此它抛出了异常。

    为了解决这个问题,我还必须在创建 ByteArrayResource 的实例时重写 contentLength() 方法。达达!

        ByteArrayResource fileAsResource = new ByteArrayResource(file.getBytes()) {
    
            @Override
            public String getFilename() {
                return file.getOriginalFilename();
            }
    
            @Override
            public long contentLength() throws IOException {
                return file.getSize();
            }
        };
    

    如果有人遇到同样的问题,希望这会有所帮助。

    【讨论】:

    • 为我工作。谢谢。
    • 很高兴它有帮助。干杯!
    【解决方案2】:

    接受的答案无效。在我的情况下,我必须覆盖 getFile(),请参阅下面的解决方案。

    registry.addResourceHandler("/my-app/user-tracking-script.js")
                    .setCachePeriod(0)
                    .resourceChain(false)
                    .addResolver(new ResourceResolver() {
                        @Override
                        public Resource resolveResource(final HttpServletRequest request, final String requestPath, final List<? extends Resource> locations, final ResourceResolverChain chain) {
                            try {
                                final HttpHeaders headers = new HttpHeaders();
                                headers.setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM));
    
                                final HttpEntity<String> entity = new HttpEntity<>(headers);
    
    // RELEVANT PART BELOW
                                final ResponseEntity<byte[]> response = restTemplate.exchange(userTrackingScript, HttpMethod.GET, entity, byte[].class);
                                final ByteArrayResource fileAsResource = new ByteArrayResource(response.getBody()) {
                                    @Override
                                    public File getFile() throws IOException {
                                        final File tempFile = File.createTempFile("user-tracking", ".js");
                                        try (final FileOutputStream out = new FileOutputStream(tempFile)) {
                                            IOUtils.copy(new ByteArrayInputStream(response.getBody()), out);
                                        }
                                        return tempFile;
                                    }
                                };
                                return fileAsResource;
                            } catch (final Exception e) {
                                log.error("Could not download user-tracking-script.js for URL: {}", userTrackingScript, e);
                            }
                            return null;
                        }
    
                        @Override
                        public String resolveUrlPath(final String resourcePath, final List<? extends Resource> locations, final ResourceResolverChain chain) {
                            log.error("Unexpected call to resolveUrlPath by {}", resourcePath);
                            return null;
                        }
                    })
            ;
    

    【讨论】:

      猜你喜欢
      • 2015-07-05
      • 2013-12-13
      • 2013-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-09
      相关资源
      最近更新 更多