【问题标题】:Subscribe didn't receive a response to download the file订阅没有收到下载文件的响应
【发布时间】:2019-09-05 12:03:43
【问题描述】:

在我的项目中,我使用 angular6 和 Springboot 后端。所以我想做的是使用这个控制器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 类中,字母会正确生成。

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

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);
  });
}

在上面的函数中,响应不会被捕获,因为结果是

错误消息:“OK”

这很令人困惑,因为它只显示“OK”,没有任何具体的错误详细信息。此外,在我的前端服务中成功发送获取请求,并且 chrome 开发工具中的网络内选项卡显示“状态代码:200”

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

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

【问题讨论】:

  • 您需要请求选项以将用户名/密码作为标头传递。它没有在您的控制器中收到。不会出现弹出窗口,因为您正在执行 Ajax 请求,该请求是在浏览器后台处理的。
  • @M.Deinum 更新了我的问题,你有什么想法吗?
  • 您正在使用 AJAX 下载文件,因此请求/响应是透明处理的,因此不会弹出窗口。
  • @M.Deinum 那么我应该怎么做才能解决这个问题。请您详细说明一下?
  • 如果您想要一个弹出窗口但想要一个常规链接,请不要使用 AJAX。您正在后台执行请求,因此所有内容都在后台处理。你需要做额外的工作,见stackoverflow.com/questions/35138424/…

标签: angular spring-mvc httpresponse


【解决方案1】:

正如 M. 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 将是您后端的网址。它应该会弹出一个下载对话框(我没有针对来自后端的文件进行测试,但我认为这应该可以)。

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

【讨论】:

  • 感谢您的回答。我会试试这个,请你告诉我透明地获取 AJAX 请求的原因是什么
  • 你是救生员。这应该会赢得更多的支持@thomi
  • NP,很高兴我能帮上忙。
猜你喜欢
  • 2020-10-06
  • 2021-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-31
  • 2015-02-08
  • 2021-09-12
  • 1970-01-01
相关资源
最近更新 更多