Cle*_*mzd 13 java spring spring-mvc
我正在尝试使用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);
Run Code Online (Sandbox Code Playgroud)
我尝试过以下哪些不起作用:
我一直在调试反序列化,但要理解它真是太痛苦了!
如果它可以帮助,使用一个文件,使用转换器' ResourceHttpMessageConverter'.
有人有想法吗?
编辑:如果我按地图中的文件(而不是列表)添加每个文件,请求将起作用.
for (MultipartFile fichier : fichiers) {
map.add("files", new ByteArrayResource(fichier.getBytes()) {
@Override
public String getFilename()
{
return fichier.getOriginalFilename();
}
});
};
Run Code Online (Sandbox Code Playgroud)
但我得到另一个例外: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>
Run Code Online (Sandbox Code Playgroud)
我在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);
Run Code Online (Sandbox Code Playgroud)
我添加了这个:
this.restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor(username, password));
Run Code Online (Sandbox Code Playgroud)
这堂课是:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 1
在 Spring Security 配置文件中缺少身份验证提供程序。你可以尝试这个而不是拦截器
<authentication-manager>
<authentication-provider>
<user-service>
<user name="user" password="password" />
</user-service>
</authentication-provider>
</authentication-manager>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
750 次 |
| 最近记录: |