从HTTP POST调用下载PDF

时间:2014-06-10 02:06:22

标签: forms angularjs http pdf

以下是我在不使用JQuery的情况下想要完成的事情(IE 9 +,Chrome,FF,Safari):

  1. 使用某些数据对我的API端点进行http POST调用
  2. 服务器动态生成PDF并将PDF作为二进制附件返回
  3. 浏览器执行默认下载行为并下载PDF而不刷新页面
  4. 基本上我希望得到类似于<a href="test.pdf">的行为,但是在进行POST调用而不是GET调用之后,动态生成的PDF。

    我尝试过很多不同的东西,但是它们要么不能跨浏览器工作(例如使用带有blob URL的$ window.open()),要被弹出窗口拦截器阻止(任何$ window窗口调用点击范围),或者没有导致PDF自动下载(任何$ http POST解决方案)。

    我终于找到了一个似乎有用的解决方案,可以使用javascript创建表单并提交它。

      var form = document.createElement('form');
      form.setAttribute('method', 'post');
      form.setAttribute('action', myurl);
    
      var params = {foo: 'bar'};
    
      for(var key in params) {
          if(params.hasOwnProperty(key)) {
              var hiddenField = document.createElement('input');
              hiddenField.setAttribute('type', 'hidden');
              hiddenField.setAttribute('name', key);
              hiddenField.setAttribute('value', params[key]);
              form.appendChild(hiddenField);
           }
      }
    
      document.body.appendChild(form);
      form.submit();
    

    这成功完成了上述3个步骤,但现在我遇到了一个新问题。无法确定何时成功下载PDF文件。这使我无法删除表单并向用户显示友好的“请稍候...”消息。还有一个额外的问题,即提交表单会取消任何未完成的ajax请求,这也不是最佳的。

    我可以完全控制服务器和客户端,那么解决这个问题的最佳方法是什么?我不想将PDF保存在服务器上,因此在这种情况下,传回一个URL并从客户端执行第二个GET请求将不起作用。谢谢!

1 个答案:

答案 0 :(得分:0)

您可以通过应用一些HTTP标头使服务器响应作为下载行为:

Content-Type: application/octet-stream
Content-Disposition: attachment; filename="SOME_NAME.pdf"
Content-Transfer-Encoding: binary

如果您仅通过JS启动下载(而不是让用户点击下载链接),请查看this question以获取一些警告。

更新:POST语法

更新更新:使用iframe目标的表单解决方案

您可以通过让表单定位到iframe来检测您的服务器端脚本是否已完成(以及随后可以开始下载)。我相信这也应该解决取消杰出的Ajax调用的问题,但我不确定。以下是执行此操作的代码(只需在for循环之后和document.body.appendChild(form);之前将其粘贴到代码示例中):

var frame = document.createElement('iframe');
frame.setAttribute('id', 'pdfFrame');
frame.onload = function(){
    document.body.removeChild(form);
    document.body.removeChild(frame);
    alert('Download ready!');
}
document.body.appendChild(frame);
form.setAttribute('target', 'pdfFrame');

您可以将我的alert替换为您的代码,以删除“请稍候......”。