我正在尝试上传文件,然后读取它,一切正常,但是当我@Async
在处理程序方法上添加注释时,一切都没有问题。
我不希望用户一直等待,直到它处理文件。但是,在放置此注释后,我得到了java.lang.IllegalStateException: File has been moved - cannot be read again
例外。会发生什么,我该如何解决?据我了解,Spring可能只是清除文件,因为请求-响应结束并对其进行了清理。但是不应该@Async
防止这种情况吗?
样例Spring Boot应用程序:
@SpringBootApplication
@EnableSwagger2
@ComponentScan(value = "hello")
@EnableAsync
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.regex("/api/.*"))
.build();
}
}
上载控制器:
@RestController
@RequestMapping(value = "/files")
public class FilesController {
@Inject
private Upload upload;
@RequestMapping(method = RequestMethod.POST)
public void addSource(@RequestParam MultipartFile file) throws IOException, InterruptedException {
upload.process(file);
}
}
上载服务:
@Component
public class Upload {
@Async
public void process(MultipartFile file) throws InterruptedException, IOException {
sleep(2000);
System.out.println(new String(IOUtils.readFully(file.getInputStream(), -1, false)));
}
}
现在我明白了java.io.FileNotFoundException
。我不确定我在这里缺少什么。可能是我做错了,因为我找不到任何错误,所以我认为这是非常常见的用例。
您不能@Async
以这种方式将MultipartFile参数传递给您的方法。
该addSource
方法结束时,MultipartFile
超出范围并释放资源。因此,“过程”方法内部的访问将失败。您可以通过这种方式建立某种竞争条件。SpringsDispatcherServlet
用于StandardServletMultipartResolver.cleanupMultipart
清理那些文件。在该处放置一个断点,以查看何时重新调用该方法addSource(...)
。
您应该执行以下操作:将整个文件读入addSource
方法内部的Buffer中。然后将缓冲区传递给process
Method并让其addSource
返回。
您所说的“ ...正在处理文件...”不是在“处理”文件,而是在读取文件。
@Async
public void process(byte[] bs){
System.out.println(new String(bs));
//do some long running processing of bs here
}
@RequestMapping(method = RequestMethod.POST)
public void addSource(@RequestParam MultipartFile file) {
upload.process(IOUtils.toByteArray(file));
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句