2016-11-25 77 views
11

我試圖用Spring Rest發送文件列表,但我得到此異常。春季休息 - 發送文件列表時發生異常

Could not write content: No serializer found for class java.io.ByteArrayInputStream

它與一個文件(ByteArrayResource)。

它不適用於文件列表(List<ByteArrayResource>)。

這裏是我的代碼的重要部分:

List<ByteArrayResource> contentsAsResource = new ArrayList<ByteArrayResource>(); 
for(MultipartFile fichier : fichiers) { 
    contentsAsResource.add(new ByteArrayResource(fichier.getBytes()) { 
     @Override 
     public String getFilename() 
     { 
      return fichier.getOriginalFilename(); 
     } 
    }); 
}; 
map.add("files", contentsAsResource); 
HttpHeaders headers = new HttpHeaders(); 
headers.setContentType(MediaType.MULTIPART_FORM_DATA); 
HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<LinkedMultiValueMap<String, Object>>(map, headers); 

FormHttpMessageConverter formConverter = new FormHttpMessageConverter(); 
formConverter.setMultipartCharset(Charset.forName("UTF8")); 
formConverter.addPartConverter(new MappingJackson2HttpMessageConverter()); 

this.restClientHelper.getRestTemplate().getMessageConverters().add(formConverter); 
this.restClientHelper.getRestTemplate().postForObject("file/save", requestEntity, Object.class); 

我試過,沒有工作的情況如下:

  • 發送一個數組,而不是一個列表
  • 包裝清單在DTO
  • 發送字節[],但它並沒有在文件工作>有1.5Mb

我一直在調試反序列化,但理解起來非常痛苦!

如果它可以幫助,使用一個文件,轉換器'ResourceHttpMessageConverter'被使用。

任何人有想法嗎?

編輯:如果我通過文件在地圖(而不是列表)中添加每個文件,請求的作品。

for (MultipartFile fichier : fichiers) { 
    map.add("files", new ByteArrayResource(fichier.getBytes()) { 
    @Override 
    public String getFilename() 
    { 
     return fichier.getOriginalFilename(); 
    } 
    }); 
}; 

但我得到另一個例外:org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:8080/myApp/ws/file/save"。在目標服務器上啓用了基本身份驗證。如果我禁用它,一切正常!以下是目標服務器上的spring-security配置。

<http pattern="/ws/file/**" authentication-manager-ref="basicAuthenticationManager" create-session="stateless"> 
     <intercept-url pattern="/**" access="isAuthenticated()"/> 
     <http-basic /> 

     <csrf disabled="true" /> 
     <headers disabled="true" /> 
</http> 

我在彈簧安全配置中丟失了什麼嗎?

編輯2:好像沒有在報頭中的令牌「授權」,將它添加手動解決問題

編輯3:問題解決了!當使用基本身份驗證啓用時,將具有彈簧休息模板的多個文件發送到目標服務器時,需要(重新)添加基本身份驗證令牌。這裏有很好的解釋:Basic authentication for REST API using spring restTemplate。我不知道它是否是一個錯誤(從Spring開始)。此更新之前,我的配置(我選擇的攔截方法)是這樣的:

final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); 
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(login, motDePasse)); 
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); 
... 
final HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); 
requestFactory.setHttpClient(httpClientBuilder.build()); 
this.restTemplate = new RestTemplate(requestFactory); 

我已經添加了這一點:

this.restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor(username, password)); 

類是:

private static class BasicAuthorizationInterceptor implements ClientHttpRequestInterceptor 
{ 

    private final String username; 

    private final String password; 

    public BasicAuthorizationInterceptor(String username, String password) 
    { 
    this.username = username; 
    this.password = (password == null ? "" : password); 
    } 

    @Override 
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException 
    { 
    byte[] token = Base64.getEncoder().encode((this.username + ":" + this.password).getBytes()); 
    request.getHeaders().add("Authorization", "Basic " + new String(token)); 
    return execution.execute(request, body); 
    } 

    } 
+0

[請參閱本文](http:// stackoverflow。com/questions/25103070/resttemplate-httpmessagenotwritableexception-no-serializer-found-for-class-ja) – Onkar

+0

謝謝。我看過這篇文章。我的代碼非常相似。 – Clemzd

+0

所以你的問題不再是關於春天的休息模板,而是春天的安全?如果你想支持目標服務器上的安全性,你的請求應該被認證(設置頭文件例如:'Authorization:Basic QWxhZGRpbjpPcGVuU2VzYW1l' –

回答

0
春季安全配置

文件缺少驗證提供程序。 你可以試試這個,而不是攔截器

<authentication-manager> 
    <authentication-provider> 
     <user-service> 
     <user name="user" password="password" /> 
     </user-service> 
    </authentication-provider> 
</authentication-manager>