我正在尝试发送一个包含
Spring Rest的文件列表,但是我收到这个异常.
无法写入内容:找不到类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:POST请求“http:// localhost:8080 / myApp / ws / file / save”上的I / O错误.目标服务器上启用了基本身份验证.如果我禁用它,一切正常!这是目标服务器上的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>
我在春天的安全配置中缺少一些东西吗?
编辑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); } }