从HTTP POST调用下载PDF
以下是我想要完成的(IE 9+,Chrome,FF,Safari),而不使用JQuery:
基本上我想获得类似于<a href="test.pdf">
的行为,但是对于一个动态生成的PDF进行POST调用而不是GET调用后。
我尝试了很多不同的东西,但是它们要么不能跨浏览器工作(例如使用带有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请求在这种情况下不起作用。 谢谢!
您可以通过应用一些HTTP标头使服务器响应像下载一样运行:
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="SOME_NAME.pdf"
Content-Transfer-Encoding: binary
如果您只通过JS启动下载(而不是让用户点击下载链接),那么请查看此问题以了解一些注意事项。
更新: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
,以删除“请稍候...”。