首页 > 解决方案 > 从 Java Spring 下载 - OpenWith/Save 对话框在完成之前不会出现

问题描述

问题:POST在请求完成之前,不会出现打开方式/保存文件对话框。用户将单击下载链接,然后在 X 分钟后(X 随文件大小增加),打开方式/保存文件对话框出现。我希望对话框立即出现并立即跟踪进度,而不是在请求完成后。

问题:如何确保用户立即看到“打开方式”/“保存”对话框,并且下载进度立即显示在浏览器的“下载”菜单中,而不是在POST请求完成后显示?

客户端代码(角度):

downloadFile(){
  this.documentApi.postDownloadFile(this.fileId).subscribe(data => {
    var link = document.createElement("a");
    link.href = window.URL.createObjectURL(data);
    link.download= this.fileName;
    link.dispatchEvent(new MouseEvent(`click`, {bubbles: true, cancelable: true, view: window}));
  });
}

postDownloadFile(id): Observable<any> {
  let httpOptions = {
    headers: new HttpHeaders({
      'Accept': 'text/html, application/xhtml+xml, */*',
      'Content-Type': 'application/octet-stream'
    }),
    responseType: 'blob' as 'blob'
  };
  return this.http.post(`${BaseUrl}reviewDocument/downloadFile`, id, httpOptions).pipe(
    catchError(this.handleError) 
  );
}

Java 代码:

@RequestMapping(value="/reviewDocument/downloadFile", method = RequestMethod.POST, produces="application/octet-stream")
public void downloadFile(HttpServletResponse response, @RequestBody String fileId) throws IOException {
    try{

        File file = new File(getFilePath(fileId));

        response.setContentType("application/octet-stream");

        response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getName()));

        response.setContentLength((int)file.length());

        InputStream inputStream = new FileInputStream(file); 

        int read=0;
        byte[] bytes = new byte[1024];
        OutputStream os = response.getOutputStream();

        while((read = inputStream.read(bytes))!= -1){
            os.write(bytes, 0, read);
        }
        os.flush();
        os.close(); 

    }
    catch(Exception ex){
        System.out.println(ex);
    }
}

我最初是这样返回文件的: return ResponseEntity.ok().body(FileCopyUtils.copyToByteArray(inputStream));当文件很大时,这会导致内存不足错误。

内存不足问题似乎已通过使用Outputstream. 我也尝试过使用IOUtils,但它似乎与写入输出流相同,并且由于我没有遇到任何内存不足错误,因此我没有再次重构。

无论如何,无论我尝试了什么解决方案,打开方式/保存文件的提示都会延迟,直到请求完全完成。浏览器“下载”菜单中也没有显示任何内容。对于图像和 pdf 等,这不是问题,因为文件大小很小,因此请求花费的时间更少,但是每当提供大文件时,这个问题就会很明显,因为请求花费的时间更长。

研究其他 SO 问题:

从 RestFul Java Spring 后端下载 Angular 文件- 此人说他有一个解决方法,但没有提供。我试图根据他的回答进行实验,但没有运气。

使用 HTML5/Javascript 生成和保存文件- 这似乎只是解决了下载客户端内容的问题。

还有许多其他示例,但除了第一个链接,这是一个被否决的问题,我找不到任何特定于我的问题的东西。

编辑:根据评论的指导,我切换到GETfrom POST,但经历了相同的行为。

标签: javascriptjavaangularspring

解决方案


推荐阅读