簡體   English   中英

Spring Rest - 發送文件列表時的異常

[英]Spring Rest - Exception when sending a List of files

我正在嘗試使用Spring Rest發送文件列表,但是我得到了這個例外。

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

它適用於一個文件( ByteArrayResource )。

它不適用於文件List<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中
  • 發送bytes []但是當文件> 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>

我在Spring安全配置中遺漏了什么?

編輯2:似乎標題中沒有令牌“授權”,添加它手動修復問題

編輯3:問題解決了! 當使用Spring rest模板將多個文件發送到啟用了基本身份驗證的目標服務器時,需要(重新)添加基本的身份驗證令牌。 這里有很好的解釋: 使用spring restTemplate對REST API進行基本身份驗證 我不知道它是不是一個bug(來自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);
   }

  }

在spring安全配置文件中缺少身份驗證提供程序。 你可以試試這個攔截器

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM