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

我需要在“文件下载控制器”之上编写一个“一次性文件下载”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 版本。

我的代码有什么问题?我没有完全发布它以保持简单,但是调试我看到写操作成功并具有正确的有效负载。


LEATH
浏览 125回答 2
2回答

慕仙森

我有同样的问题。就我而言,解决方案是配置一个AsyncTaskExecutor:@Configurationpublic class WebConfig extends WebMvcConfigurerAdapter {&nbsp; &nbsp; @Override&nbsp; &nbsp; public void configureAsyncSupport(AsyncSupportConfigurer configurer) {&nbsp; &nbsp; &nbsp; &nbsp; configurer.setDefaultTimeout(-1);&nbsp; &nbsp; &nbsp; &nbsp; configurer.setTaskExecutor(asyncTaskExecutor());&nbsp; &nbsp; }&nbsp; &nbsp; @Bean&nbsp; &nbsp; public AsyncTaskExecutor asyncTaskExecutor() {&nbsp; &nbsp; &nbsp; &nbsp; // an implementaiton of AsyncTaskExecutor&nbsp; &nbsp; &nbsp; &nbsp; return new SimpleAsyncTaskExecutor("async");&nbsp; &nbsp; }}

守着一只汪

根据@MDenium 的评论不要使用供内部使用的 WebAsyncTask。只需使用 CompletableFuture 或返回 Callable。如果您将 try/finally 放在 Callable 中,它将起作用WebAsyncTask 只是不是一个 API,因此当您从 MVC 方法返回时,Spring 不知道如何处理它。这不是执行异步执行的正确方法。它仅在内部用于承载任务和上下文。Spring MVC 支持:延迟结果可调用可完成的未来大概一个少数人
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java