使用Ajax下载并打开PDF文件

Nay*_*ayn 88 javascript java pdf jquery

我有一个生成PDF的动作类.该contentType适当地设定.

public class MyAction extends ActionSupport 
{
   public String execute() {
    ...
    ...
    File report = signedPdfExporter.generateReport(xyzData, props);

    inputStream = new FileInputStream(report);
    contentDisposition = "attachment=\"" + report.getName() + "\"";
    contentType = "application/pdf";
    return SUCCESS;
   }
}
Run Code Online (Sandbox Code Playgroud)

action 通过Ajax调用来调用它.我不知道将此流传递给浏览器的方法.我尝试过一些东西,但没有任何效果.

$.ajax({
    type: "POST",
    url: url,
    data: wireIdList,
    cache: false,
    success: function(response)
    {
        alert('got response');
        window.open(response);
    },
    error: function (XMLHttpRequest, textStatus, errorThrown) 
    {
        alert('Error occurred while opening fax template' 
              + getAjaxErrorString(textStatus, errorThrown));
    }
});
Run Code Online (Sandbox Code Playgroud)

以上给出了错误:

您的浏览器发送了此服务器无法理解的请求.

May*_*ala 114

这是我如何工作的方式

$.ajax({
  url: '<URL_TO_FILE>',
  success: function(data) {
    var blob=new Blob([data]);
    var link=document.createElement('a');
    link.href=window.URL.createObjectURL(blob);
    link.download="<FILENAME_TO_SAVE_WITH_EXTENSION>";
    link.click();
  }
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

使用download.js更新了答案

$.ajax({
  url: '<URL_TO_FILE>',
  success: download.bind(true, "<FILENAME_TO_SAVE_WITH_EXTENSION>", "<FILE_MIME_TYPE>")
});
Run Code Online (Sandbox Code Playgroud)

  • 它适用于chrome吗?我只能看到一个空白的pdf. (24认同)
  • 这个(锚元素)在IE 11,Edge和Firefox上实际上对我不起作用.将成功改为仅使用"window.open(URL.createObjectURL(blob))"确实有效. (5认同)
  • 我可以通过在“$.ajax()”的参数中添加“xhrFields: { responseType: 'blob' }”来解决空白 PDF 问题。 (5认同)
  • 已下载pdf文件,但不提供任何内容.我在服务器端保存了byte [],并且可以使用pdf内容.PLZ建议. (2认同)
  • 下载空白pdf文件. (2认同)

Bal*_*usC 37

你不一定需要Ajax.只是一个<a>环节是不够的,如果你设置content-dispositionattachment服务器端代码.这样父页面就会保持打开状态,如果这是你的主要关注点(为什么你会不必要地选择Ajax呢?).此外,没有办法很好地同步处理这个问题.PDF不是字符数据.这是二进制数据.你不能做的事情$(element).load().您想对此使用全新的请求.因为那<a href="pdfservlet/filename.pdf">pdf</a>是非常合适的.

为了更多地帮助您使用服务器端代码,您需要详细了解所使用的语言并发布代码尝试的摘录.

  • 再一次:你**不要**需要Ajax.这只是要求麻烦.PDF是二进制数据,而不是HTML或JSON等字符数据. (6认同)
  • 在某些浏览器中,window.open将保持打开状态并且空白,这对于最终用户来说可能很烦人.所以,也不要使用window.open.如果`content-disposition`设置为`attachment`,你将得到一个'另存为'对话框.父页面将保持不变.只需`<a href="pdfservlet/filename.pdf"> pdf </a>`或`<form action ="pdfservlet/filename.pdf"> <input type ="submit"> </ form>`够了. (5认同)
  • Url长度有限.作者问的是POST. (4认同)
  • var url = contextPath +"/ xyz/theblahBlah.action"; url + = url +"?" + params; 试试{var child = window.open(url); child.focus(); } catch(e){} (3认同)
  • 同意@EdwardOlamisan,这不是正确的答案,因为作者试图对数据进行“ POST”。 (3认同)
  • 附件的内容处理不适用于 Ajax。我无法提供超链接,因为文档是在服务器端动态生成的。 (2认同)
  • 这实际上并没有回答这个问题。 (2认同)

chi*_*oro 30

我真的不认为过去的任何答案都发现了原始海报的问题.当海报试图发布数据并获得响应下载时,他们都假设一个GET请求.

在寻找任何更好的答案的过程中,我们发现了这个用于请求类Ajax文件下载的jQuery插件.

在它的"心脏"中,它创建一个"临时"HTML表单,其中包含给定数据作为输入字段.此表单附加到文档并发布到所需的URL.在此之后,表单再次被删除:

jQuery('<form action="'+ url +'" method="'+ (method||'post') +'">'+inputs+'</form>')
    .appendTo('body').submit().remove()
Run Code Online (Sandbox Code Playgroud)

与我提到的jQuery插件相比,更新 Mayur的答案看起来非常有前途且非常简单.


Geo*_*lou 9

这就是我如何解决这个问题.
乔纳森·阿门德在这篇文章中的答案对我帮助很大.
以下示例已简化.

有关更多详细信息,上面的源代码能够使用JQuery Ajax请求(GET,POST,PUT等)下载文件.它还有助于将参数上传为JSON并将内容类型更改为application/json(我的默认值).

HTML源:

<form method="POST">
    <input type="text" name="startDate"/>
    <input type="text" name="endDate"/>
    <input type="text" name="startDate"/>
    <select name="reportTimeDetail">
        <option value="1">1</option>
    </select>
    <button type="submit"> Submit</button>
</form>  
Run Code Online (Sandbox Code Playgroud)

一个带有两个输入文本,一个选择和一个按钮元素的简单表单.

JavaScript的网页来源:

<script type="text/javascript" src="JQuery 1.11.0 link"></script>
<script type="text/javascript">
    // File Download on form submition.
    $(document).on("ready", function(){
        $("form button").on("click", function (event) {
            event.stopPropagation(); // Do not propagate the event.

            // Create an object that will manage to download the file.
            new AjaxDownloadFile({
                url: "url that returns a file",
                data: JSON.stringify($("form").serializeObject())
            });

            return false; // Do not submit the form.
        });
    });
</script>  
Run Code Online (Sandbox Code Playgroud)

点击按钮时的简单事件.它创建了一个AjaxDownloadFile对象.AjaxDownloadFile类源代码如下.

AjaxDownloadFile类来源:

var AjaxDownloadFile = function (configurationSettings) {
    // Standard settings.
    this.settings = {
        // JQuery AJAX default attributes.
        url: "",
        type: "POST",
        headers: {
            "Content-Type": "application/json; charset=UTF-8"
        },
        data: {},
        // Custom events.
        onSuccessStart: function (response, status, xhr, self) {
        },
        onSuccessFinish: function (response, status, xhr, self, filename) {
        },
        onErrorOccured: function (response, status, xhr, self) {
        }
    };
    this.download = function () {
        var self = this;
        $.ajax({
            type: this.settings.type,
            url: this.settings.url,
            headers: this.settings.headers,
            data: this.settings.data,
            success: function (response, status, xhr) {
                // Start custom event.
                self.settings.onSuccessStart(response, status, xhr, self);

                // Check if a filename is existing on the response headers.
                var filename = "";
                var disposition = xhr.getResponseHeader("Content-Disposition");
                if (disposition && disposition.indexOf("attachment") !== -1) {
                    var filenameRegex = /filename[^;=\n]*=(([""]).*?\2|[^;\n]*)/;
                    var matches = filenameRegex.exec(disposition);
                    if (matches != null && matches[1])
                        filename = matches[1].replace(/[""]/g, "");
                }

                var type = xhr.getResponseHeader("Content-Type");
                var blob = new Blob([response], {type: type});

                if (typeof window.navigator.msSaveBlob !== "undefined") {
                    // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed.
                    window.navigator.msSaveBlob(blob, filename);
                } else {
                    var URL = window.URL || window.webkitURL;
                    var downloadUrl = URL.createObjectURL(blob);

                    if (filename) {
                        // Use HTML5 a[download] attribute to specify filename.
                        var a = document.createElement("a");
                        // Safari doesn"t support this yet.
                        if (typeof a.download === "undefined") {
                            window.location = downloadUrl;
                        } else {
                            a.href = downloadUrl;
                            a.download = filename;
                            document.body.appendChild(a);
                            a.click();
                        }
                    } else {
                        window.location = downloadUrl;
                    }

                    setTimeout(function () {
                        URL.revokeObjectURL(downloadUrl);
                    }, 100); // Cleanup
                }

                // Final custom event.
                self.settings.onSuccessFinish(response, status, xhr, self, filename);
            },
            error: function (response, status, xhr) {
                // Custom event to handle the error.
                self.settings.onErrorOccured(response, status, xhr, self);
            }
        });
    };
    // Constructor.
    {
        // Merge settings.
        $.extend(this.settings, configurationSettings);
        // Make the request.
        this.download();
    }
};
Run Code Online (Sandbox Code Playgroud)

我创建了这个类来添加到我的JS库中.它是可重复使用的.希望有所帮助.

  • IE10 +支持`Blob`对象. (2认同)

Nin*_*nja 6

为了解决post请求中的空白PDF问题以获取PDF等流数据,我们需要在请求中添加响应类型为'arraybuffer'或'blob'

$.ajax({
  url: '<URL>',
  type: "POST",
  dataType: 'arraybuffer',
  success: function(data) {
    let blob = new Blob([data], {type: 'arraybuffer'});
    let link = document.createElement('a');
    let objectURL = window.URL.createObjectURL(blob);
    link.href = objectURL;
    link.target = '_self';
    link.download = "fileName.pdf";
    (document.body || document.documentElement).appendChild(link);
    link.click();
    setTimeout(()=>{
        window.URL.revokeObjectURL(objectURL);
        link.remove();
    }, 100);
  }
});
Run Code Online (Sandbox Code Playgroud)


Ija*_*een 5

您可以使用此插件创建表单,然后提交表单,然后将其从页面中删除.

jQuery.download = function(url, data, method) {
    //url and data options required
    if (url && data) {
        //data can be string of parameters or array/object
        data = typeof data == 'string' ? data : jQuery.param(data);
        //split params into form inputs
        var inputs = '';
        jQuery.each(data.split('&'), function() {
            var pair = this.split('=');
            inputs += '<input type="hidden" name="' + pair[0] +
                '" value="' + pair[1] + '" />';
        });
        //send request
        jQuery('<form action="' + url +
                '" method="' + (method || 'post') + '">' + inputs + '</form>')
            .appendTo('body').submit().remove();
    };
};


$.download(
    '/export.php',
    'filename=mySpreadsheet&format=xls&content=' + spreadsheetData
);
Run Code Online (Sandbox Code Playgroud)

这对我有用.在这里找到这个插件


Par*_*Par 5

对我来说有用的是以下代码,因为服务器功能正在检索 File(memoryStream.GetBuffer(), "application/pdf", "fileName.pdf");:

$http.get( fullUrl, { responseType: 'arraybuffer' })
            .success(function (response) {
                var blob = new Blob([response], { type: 'application/pdf' });

                if (window.navigator && window.navigator.msSaveOrOpenBlob) {
                    window.navigator.msSaveOrOpenBlob(blob); // for IE
                }
                else {
                    var fileURL = URL.createObjectURL(blob);
                    var newWin = window.open(fileURL);
                    newWin.focus();
                    newWin.reload();
                }
});
Run Code Online (Sandbox Code Playgroud)


Vpa*_*ant 5

关于Mayur Padshala给出的回答这是通过 ajax 下载 pdf 文件的正确逻辑,但正如其他人在评论中报告的那样,该解决方案确实下载了一个空白的 pdf。

其原因在此问题的已接受答案中进行了解释:jQuery 在使用 AJAX 请求加载二进制数据时存在一些问题,因为它尚未实现某些 HTML5 XHR v2 功能,请参阅此增强请求和此讨论

所以使用HTMLHTTPRequest代码应该是这样的:

var req = new XMLHttpRequest();
req.open("POST", "URL", true);
req.responseType = "blob";
req.onload = function (event) {
    var blob = req.response;
    var link=document.createElement('a');
    link.href=window.URL.createObjectURL(blob);
    link.download="name_for_the_file_to_save_with_extention";
    link.click();
}
Run Code Online (Sandbox Code Playgroud)


Mem*_*emZ 5

以下代码对我有用

//Parameter to be passed
var data = 'reportid=R3823&isSQL=1&filter=[]';
var xhr = new XMLHttpRequest();
xhr.open("POST", "Reporting.jsp"); //url.It can pdf file path
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.responseType = "blob";
xhr.onload = function () {
    if (this.status === 200) {
        var blob = new Blob([xhr.response]);
        const url = window.URL.createObjectURL(blob);
        var a = document.createElement('a');
        a.href = url;
        a.download = 'myFile.pdf';
        a.click();
        setTimeout(function () {
            // For Firefox it is necessary to delay revoking the ObjectURL
            window.URL.revokeObjectURL(data)
                , 100
        })
    }
};
xhr.send(data);
Run Code Online (Sandbox Code Playgroud)