从Ajax响应中下载PDF文件

12

我正在尝试使浏览器从ajax响应中下载pdf文件。

受到 Download pdf file using jquery ajax 的启发,我像这样模拟点击/下载事件:

    var req = new XMLHttpRequest();
    req.open("POST", "/servicepath/Method?ids=" + ids, true);
    req.responseType = "blob";
    req.onreadystatechange = function () {
        if (req.readyState === 4 && req.status === 200) {
            var blob = req.response;
            var link = document.createElement('a');
            link.href = window.URL.createObjectURL(blob);
            link.download = "PdfName-" + new Date().getTime() + ".pdf";
            link.click();
        }
    };
    req.send();

不幸的是,这只在Chrome中起作用,但在Firefox和IE中则不起作用。我尝试在最后两个浏览器中触发它时,什么也没有发生。

由于从CMS继承,脚本和标记被放置在一个iframe内,但我不确定这是否会产生任何影响。

有什么想法可以优化它以适用于所有现代浏览器吗?


你有没有遇到任何错误? - XCS
请检查IE浏览器的控制台,如果有任何错误,请告诉我们。 - Vignesh Subramanian
3个回答

21

这个版本可以在所有现代浏览器上使用:

var req = new XMLHttpRequest();
req.open("POST", "/servicepath/Method?ids=" + ids, true);
req.responseType = "blob";
req.onreadystatechange = function () {
    if (req.readyState === 4 && req.status === 200) {
        var filename = "PdfName-" + new Date().getTime() + ".pdf";
        if (typeof window.chrome !== 'undefined') {
            // Chrome version
            var link = document.createElement('a');
            link.href = window.URL.createObjectURL(req.response);
            link.download = "PdfName-" + new Date().getTime() + ".pdf";
            link.click();
        } else if (typeof window.navigator.msSaveBlob !== 'undefined') {
            // IE version
            var blob = new Blob([req.response], { type: 'application/pdf' });
            window.navigator.msSaveBlob(blob, filename);
        } else {
            // Firefox version
            var file = new File([req.response], filename, { type: 'application/force-download' });
            window.open(URL.createObjectURL(file));
        }
    }
};
req.send();

我也尝试获取 Safari 版本,但效果不是很好。我会继续研究并为此提供解决方案。


我选择了gaetanoM的答案,因为他最先回答了,但是我在之后测试了你的脚本,它也能正常工作 - 谢谢(我投了赞成票)。 - user653522
其实我是第一个 :( 23小时前回答的。 - Dekel
抱歉,我错了 :/ 他先回复了,所以我以为他在你之前.. 你知道我是否可以为你添加额外的赏金吗? - user653522
您可以为每个问题添加赏金,并将其授予新的或现有的答案。您可以在此处阅读更多信息 - Dekel
1
酷,23小时后有赏金等着你 :) - user653522
你从哪里找到这些与浏览器下载相关的资料?有没有适当的文档来解释这种东西?如果有任何有用的资源,请分享,因为我想要理解整个代码。 - Umar Asghar

16

有什么办法可以优化它以适用于所有现代浏览器吗?

是的,我可以给您一个在Windows 10上测试过的解决方案,可在IE11、Firefox47和Chrome52上使用。目前还没有针对Microsoft Edge的解决方案。

在开始之前,您需要区分您是否在使用IE或其他两个浏览器。这是因为在IE11上您可以使用:

window.navigator.msSaveBlob(req.response, "PdfName-" + new Date().getTime() + ".pdf");

对于另外两个浏览器,你的代码可以在Chrome上运行,但无法在Firefox上运行,因为你没有将元素附加到文档主体中。

因此,修正后的代码如下:

var req = new XMLHttpRequest();
req.open("POST", "/servicepath/Method?ids=" + ids, true);
req.responseType = "blob";
req.onreadystatechange = function () {
  if (req.readyState === 4 && req.status === 200) {

    // test for IE

    if (typeof window.navigator.msSaveBlob === 'function') {
      window.navigator.msSaveBlob(req.response, "PdfName-" + new Date().getTime() + ".pdf");
    } else {
      var blob = req.response;
      var link = document.createElement('a');
      link.href = window.URL.createObjectURL(blob);
      link.download = "PdfName-" + new Date().getTime() + ".pdf";

      // append the link to the document body

      document.body.appendChild(link);

      link.click();
    }
  }
};
req.send();

@AndiAR 我不知道。我从来没有使用过Safari。你可以测试一下并让我知道吗?非常感谢。 - gaetanoM

0

非常简单的下载文件方法...

 $.ajax({
        url:"{{url('.......')}}/"+customerOrderId,
        type:'post',
        data:{"_token":"{{csrf_token()}}"},
        success:function(e){
            console.log(e.file);
            var link = document.createElement('a');
            link.href = e.file;
            link.download = "invoice_"+customerOrderId+"_" + new Date() + ".pdf";
            link.click();
            link.remove()

        },
        error:function(e){
            alert('Something went wrong!');
        }
    });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接