订阅未收到下载文件的响应

时间:2019-09-05 12:03:43

标签: angular spring-mvc httpresponse

在我的项目中,我使用的是带有Springboot后端的angular6。所以我想做的是使用此控制器Java类弹出保存对话框,

@RequestMapping(value = "/getGeneratedLetter/{userId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public void genarateLetter(@PathVariable("userId") Integer userId, HttpServletResponse response) {
        System.out.println(userId);
        letterTypeService.genarateLetter(userId);
        try {
            // get Letter.docx from file path
            InputStream is = new FileInputStream("Letter.docx");
            response.setHeader("Content-Disposition", "attachment; filename = Letter.docx");
            IOUtils.copy(is, response.getOutputStream());
            response.flushBuffer();
        } catch (Exception ex) {
            throw new RuntimeException("IOError in " + ex);
        }
    }

注意:在我的letterTypeService Java类中,该字母将正确生成。

最后,我在组件的前端前端捕捉响应,

getGenaratedLetterTemplate(letter) {
  this.data.getGenaratedLetterTemplate(letter.letterId).subscribe(response => {
    this.getBasicDataFromBackend();
    saveAs(response,  letter.fullName + '_' + letter.letterTypeName + '.docx');
    console.log(response);
  }, error => {
    console.log(error);
  });
}

在上面的函数中,由于结果是

,因此不会捕获响应
  

错误消息:“确定”

这令人困惑,因为它仅显示“确定”,没有任何特定的错误详细信息。另外,我在前端的服务中成功发送了获取请求,Chrome开发工具中的“网络中”标签显示了“状态码:200” enter image description here

进一步调查,当我将获取请求的URL复制并粘贴到新的浏览器窗口中时,将成功显示信件下载弹出窗口,当我单击“保存”按钮时,信件将成功下载。

那么这里可能是什么问题?

1 个答案:

答案 0 :(得分:2)

正如Deinum先生所指出的。 AJAX透明地执行GET请求,因此不会弹出。您可以在客户端中建立一个链接,单击该链接即可(就像您将链接复制到新的浏览器中一样)。例如。我为我的一个应用做了类似的事情,在我的模板中有以下内容:

 <a [href]="yourUrl" class="btn btn-primary" role="button">
     <i class="fa fa-calendar"></i> <!-- or whatever you want to display -->
 </a>

然后yourUrl将是您后端的URL。它应该弹出一个下载对话框(我没有对来自后端的文件进行测试,但是我认为这应该可行)。

修改This Answer建议您,主要出于安全原因,不能直接使用AJAX下载文件。 This codepen显示了如何使用Javascript进行操作,但基本上具有相同的作用:创建锚标记,将数据放入objectURL,将其添加到DOM,单击并再次删除自身,因此最后您会看到一个弹出窗口。笔中的download属性仅适用于同源请求,但是由于您设置了Content-Disposition标头,因此您也可以将其忽略(here is some more information about this)。为了使它与Angular一起使用,您基本上可以将success:子句中的代码复制到您的http调用中(我建议将var替换为const s)。但是,这不是干净的Angular,因为您直接与DOM交互,并且如果您使用服务器端渲染,则必须进行检查。并可能导致内存泄漏。