我正在尝试将Apache Streaming API与Spring Boot(禁用的Spring Multipart解析器)一起使用。但是,当我尝试将InputStream转换为byte []时,出现了异常-流意外终止。知道什么地方出错了吗? 代码示例:
//Server side code - Spring Boot REST Controller
@PostMapping
public ResponseEntity<MyObjectDto> upload(HttpServletRequest request)
{
FileItemIterator itemIterator;
MyObject myObject=null;
if (!ServletFileUpload.isMultipartContent(request)) {
throw new RuntimeException("Invalid content passed for upload");
}
ServletFileUpload servletFileUpload = new ServletFileUpload();
itemIterator = servletFileUpload.getItemIterator(request);
while (itemIterator.hasNext()) {
FileItemStream fileItem = itemIterator.next();
InputStream inputStream = fileItem.openStream();
if (!fileItem.isFormField()) {
byte[] bytes = IOUtils.toByteArray(inputStream);
//...Pass bytes for further processing
myObject =doSomething(bytes)
}
}
return ResponseEntity.ok(Mapper.map(myObject));
}
//Spring multipart - disabled
spring.http.multipart.enabled=false
// Client code using Apache Streaming API
Request.Post(uri)
.body(buildMultipartEntityNew(FileUtils.openInputStream(new File("src/test/resources/my.pdf"))))
.execute()
.handleResponse(responseHandler);
// Multipart Entity Builder
private static HttpEntity buildMultipartEntity(InputStream inputStream) throws JsonProcessingException {
return MultipartEntityBuilder.create()
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
.addBinaryBody("file", inputStream,
ContentType.APPLICATION_OCTET_STREAM,
"teamfile")
.build();
}
例外:
org.apache.commons.fileupload.MultipartStream $ MalformedStreamException: 流意外结束 org.apache.commons.fileupload.MultipartStream $ ItemInputStream.makeAvailable(MultipartStream.java:1005) 在 org.apache.commons.fileupload.MultipartStream $ ItemInputStream.read(MultipartStream.java:903) 在java.io.InputStream.read(InputStream.java:101)在 org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2146)在 org.apache.commons.io.IOUtils.copy(IOUtils.java:2102)在 org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2123)在 org.apache.commons.io.IOUtils.copy(IOUtils.java:2078)在 org.apache.commons.io.IOUtils.toByteArray(IOUtils.java:721)
答案 0 :(得分:0)
我发现了问题。如果有人遇到类似问题,首先要检查的是链中的任何过滤器都在尝试包装/重构请求(包含输入流)。如果您知道确切的过滤器,可以将其禁用
@Bean
public FilterRegistrationBean registration(PreAuthenticationFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean(filter);
registration.setEnabled(false);
return registration;
}
或者您可以通过全部禁用它们进行测试
public class DefaultFiltersBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf)
throws BeansException {
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)bf;
Arrays.stream(beanFactory.getBeanNamesForType(javax.servlet.Filter.class))
.forEach(
name -> {
BeanDefinition definition =
BeanDefinitionBuilder.genericBeanDefinition(FilterRegistrationBean.class)
.setScope(BeanDefinition.SCOPE_SINGLETON)
.addConstructorArgReference(name)
.addConstructorArgValue(new ServletRegistrationBean[] {})
.addPropertyValue("enabled", false)
.getBeanDefinition();
beanFactory.registerBeanDefinition(name + "FilterRegistrationBean", definition);
});
}
}
在我的情况下,自定义安全过滤器正在分解请求并重建输入流,并且它仅部分重建了输入流,因此产生了错误-MalformedStream。
我通过尝试这些选项来达到目的
security:
basic:
enabled: false
management:
security:
enabled: false
spring:
autoconfigure:
exclude: org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration
一旦我知道安全是问题所在。我仅为输入流禁用了POST的安全性,而输入流却毫发无损。
@Override public void configure(WebSecurity web) throws Exception {
web.ignoring()
.requestMatchers(ignoreNonJsonMediaTypes())
.and()
.ignoring()
.antMatchers(HttpMethod.POST);
super.configure(web);
}
private MediaTypeRequestMatcher ignoreNonJsonMediaTypes() {
MediaTypeRequestMatcher
matcher =
new MediaTypeRequestMatcher(new HeaderContentNegotiationStrategy(), MediaType.APPLICATION_JSON);
matcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
return matcher;
}