为了账号安全,请及时绑定邮箱和手机立即绑定

提供文件时“无法在没有 AsyncContext 的情况下调度”

提供文件时“无法在没有 AsyncContext 的情况下调度”

LEATH 2021-09-12 15:30:26
我需要在“文件下载控制器”之上编写一个“一次性文件下载”MVC 控制器。一旦文件被传输到客户端,它必须从服务器中删除。最初,编写代码是为了提供文件导入 org.springframework.core.io.Resource@GetMapping("/get/{someParam}")public ResponseEntity<Resource> downloadFile(Long someParam){    Long fileId = identify(someParam);    return super.downloadFile(fileId); //This uses a "File repository" service binding file IDs to physical paths}protected ResponseEntity<Resource> downloadFile(Long fileId){    File theFile = resolve(fileId);    return new FileSystemResource(theFile);}由于 ResponseEntity 是某种“未来”实体,我无法在 finally 块中删除该文件,因为它还不会被提供。所以我首先编写了一个异步版本的文件下载,利用 Commons IO 来复制有效负载。然后我利用回调来仅从我的方法中处理文件。protected WebAsyncTask<Void> downloadFileAsync(Long fileId,HttpResponse response){ //API method for multiple uses across the application    InputStream is = new FileInputStream(resolve(fileId));    Callable<Void> ret = () -> {        IOUtils.copy(is,response.getOutputStream());        is.close();        return null;    };    return ret;}@GetMapping("/get/{someParam}")public WebAsyncTask<Void> downloadFile(Long someParam,HttpResponse response){    Long fileId = identify(someParam);    WebAsyncTask ret = downloadFileAsync(fileId,response);    ret.onCompletion(()-> fileService.delete(fileId)); //Here I leverage the callback because this file, in this point, is disposable    return ret;}我已将所有 servlet 和过滤器配置为在我的web.xml. 我做了一些研究,这个答案没有帮助,因为我使用的是较新的 Tomcat 版本。我的代码有什么问题?我没有完全发布它以保持简单,但是调试我看到写操作成功并具有正确的有效负载。
查看完整描述

2 回答

?
慕仙森

TA贡献1827条经验 获得超7个赞

我有同样的问题。就我而言,解决方案是配置一个AsyncTaskExecutor:


@Configuration

public class WebConfig extends WebMvcConfigurerAdapter {


    @Override

    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {

        configurer.setDefaultTimeout(-1);

        configurer.setTaskExecutor(asyncTaskExecutor());

    }


    @Bean

    public AsyncTaskExecutor asyncTaskExecutor() {

        // an implementaiton of AsyncTaskExecutor

        return new SimpleAsyncTaskExecutor("async");

    }


}


查看完整回答
反对 回复 2021-09-12
?
守着一只汪

TA贡献1872条经验 获得超3个赞

根据@MDenium 的评论

不要使用供内部使用的 WebAsyncTask。只需使用 CompletableFuture 或返回 Callable。如果您将 try/finally 放在 Callable 中,它将起作用

WebAsyncTask 只是不是一个 API,因此当您从 MVC 方法返回时,Spring 不知道如何处理它。这不是执行异步执行的正确方法。它仅在内部用于承载任务和上下文。

Spring MVC 支持:

  • 延迟结果

  • 可调用

  • 可完成的未来

大概一个少数


查看完整回答
反对 回复 2021-09-12
  • 2 回答
  • 0 关注
  • 124 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信