使用Ajax下载并打开pdf文件

时间:2021-08-06 00:31:17

I have an action class that generates a pdf. The contentType is set appropriately.

我有一个生成pdf的action类。适当地设置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;
   }
}

I call this action through an Ajax call. I don't know the way to deliver this stream to browser. I tried a few things but nothing worked.

我通过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));
    }
});

The above gives the error:

上面给出的错误是:

Your browser sent a request that this server could not understand.

浏览器发送了一个服务器无法理解的请求。

12 个解决方案

#1


30  

You don't necessarily need Ajax for this. Just an <a> link is enough if you set the content-disposition to attachment in the server side code. This way the parent page will just stay open, if that was your major concern (why would you unnecessarily have chosen Ajax for this otherwise?). Besides, there is no way to handle this nicely acynchronously. PDF is not character data. It's binary data. You can't do stuff like $(element).load(). You want to use completely new request for this. For that <a href="pdfservlet/filename.pdf">pdf</a> is perfectly suitable.

这并不需要Ajax。如果在服务器端代码中将内容配置设置为附件,那么只需一个链接就足够了。这样,如果这是您的主要关注点,那么父页面就会保持打开状态(否则为什么您会不必要地选择Ajax呢?)此外,也没有办法很好地处理这个问题。PDF不是字符数据。这是二进制数据。不能执行$(元素).load()之类的操作。您需要为此使用全新的请求。,< a href = " pdfservlet /文件名。pdf " > pdf < / >是完全合适的。

To assist you more with the server side code, you'll need to tell more about the language used and post an excerpt of the code attempts.

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

#2


103  

Here is how I got this working

这就是我的工作原理。

$.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();
  }
});

Updated answer using download.js

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

#3


29  

I don't really think that any of the past answers spotted out the problem of the original poster. They all presume a GET request while the poster was trying to POST data and get a download in response.

我真的不认为过去的任何一个答案发现了最初海报的问题。当海报试图发布数据并得到相应的下载时,他们都假定有一个GET请求。

In the course of searching for any better answer we found this jQuery Plugin for Requesting Ajax-like File Downloads.

在寻找更好答案的过程中,我们找到了这个jQuery插件,用于请求类似ajax的文件下载。

In its "heart" it creates a "temporary" HTML form containing the given data as input fields. This form is appended to the document and posted to the desired URL. Right after that the form is removed again:

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

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

Update Mayur's answer looks pretty promising and very simple in comparison to the jQuery plug-in I referred to.

与我提到的jQuery插件相比,Update Mayur的答案看起来非常有希望,而且非常简单。

#4


6  

This is how i solve this issue.
The answer of Jonathan Amend on this post helped me a lot.
The example below is simplified.

我就是这样解决这个问题的。乔纳森·阿蒙德在这篇文章中的回答对我帮助很大。

For more details, the above source code is able to download a file using a JQuery Ajax request (GET, POST, PUT etc). It, also, helps to upload parameters as JSON and to change the content type to application/json (my default).

要了解更多细节,上面的源代码可以使用JQuery Ajax请求(GET、POST、PUT等)下载文件。它还帮助将参数上传为JSON,并将内容类型更改为application/ JSON(我的默认值)。

The html source:

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>  

A simple form with two input text, one select and a button element.

一个包含两个输入文本、一个选择和一个按钮元素的简单表单。

The javascript page source:

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>  

A simple event on button click. It creates an AjaxDownloadFile object. The AjaxDownloadFile class source is below.

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

The AjaxDownloadFile class source:

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

I created this class to added to my JS library. It is reusable. Hope that helps.

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

#5


5  

You could use this plugin.

你可以使用这个插件。

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

This worked for me. Found this plugin here

这为我工作。发现这个插件

#6


4  

What worked for me is the following code, as the server function is retrieving File(memoryStream.GetBuffer(), "application/pdf", "fileName.pdf");:

为我工作的是下面的代码,因为服务器的功能是检索文件(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();
                }
});

#7


2  

create a hidden iframe, then in your ajax code above:

创建一个隐藏的iframe,然后在上面的ajax代码中:

url: document.getElementById('myiframeid').src = your_server_side_url,

url:. getelementbyid(“myiframeid”)。src = your_server_side_url,

and remove the window.open(response);

和删除window.open(响应);

#8


1  

Do you have to do it with Ajax? Coouldn't it be a possibility to load it in an iframe?

需要用Ajax实现吗?因为有可能把它装在iframe中吗?

#9


1  

Concerning the answer given by Mayur Padshala this is the correct logic to download a pdf file via ajax but as others report in the comments this solution is indeed downloads a blank pdf.

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

The reason for this is explained in the accepted answer of this question: jQuery has some issues loading binary data using AJAX requests, as it does not yet implement some HTML5 XHR v2 capabilities, see this enhancement request and this discussion.

原因在这个问题的公认答案中得到了解释:jQuery在使用AJAX请求加载二进制数据时遇到了一些问题,因为它还没有实现一些HTML5 XHR v2功能,请参见这个增强请求和这个讨论。

So using HTMLHTTPRequest the code should look like this:

使用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();
}

#10


0  

var xhr;
var beforeSend = function(){
    $('#pleasewaitDL').modal('show');
}
$(function () {
    $('#print_brochure_link').click(function(){
        beforeSend();
        xhr = new XMLHttpRequest();
        xhr.open("GET",$('#preparedPrintModalForm').attr('action'), true); 
        xhr.responseType = "blob";
        xhr.onload = function (e) {
            if (this.status === 200) {
                var file = window.URL.createObjectURL(this.response);
                var a = document.createElement("a");
                a.href = file;
                a.download = this.response.name || "Property Brochure";
                console.log(file);
                document.body.appendChild(a);
                a.click();
                
                window.onfocus = function () {                     
                  document.body.removeChild(a)
                }
                $('#pleasewaitDL').modal('hide');
            };
        };
        xhr.send($('#preparedPrintModalForm').serialize());
    });
    $('#pleasewaitDLCancel').click(function() {
        xhr.abort();
    });
});

#11


0  

If you have to work with file-stream (so no physically saved PDF) like we do and you want to download the PDF without page-reload, the following function works for us:

如果你必须像我们一样使用文件流(所以没有物理保存的PDF),并且你想下载PDF而不需要页面重新加载,下面的功能对我们是有效的:

HTML

HTML

<div id="download-helper-hidden-container" style="display:none">
     <form id="download-helper-form" target="pdf-download-output" method="post">
            <input type="hidden" name="downloadHelperTransferData" id="downloadHelperTransferData" />
     </form>
     <iframe id="pdf-helper-output" name="pdf-download-output"></iframe>
</div>

Javascript

Javascript

var form = document.getElementById('download-helper-form');
$("#downloadHelperTransferData").val(transferData);
form.action = "ServerSideFunctionWhichWritesPdfBytesToResponse";
form.submit();

Due to the target="pdf-download-output", the response is written into the iframe and therefore no page reload is executed, but the pdf-response-stream is output in the browser as a download.

由于目标=“pdf-download-output”,响应被写入iframe,因此不会执行页面重载,但是pdf-response-stream作为下载输出在浏览器中。

#12


0  

This snippet is for angular js users which will face the same problem, Note that the response file is downloaded using a programmed click event. In this case , the headers were sent by server containing filename and content/type.

这段代码是针对角js用户的,他们将面对同样的问题,注意到响应文件是通过一个程序的点击事件下载的。在这种情况下,头文件是由包含文件名和内容/类型的服务器发送的。

$http({
    method: 'POST', 
    url: 'DownloadAttachment_URL',
    data: { 'fileRef': 'filename.pdf' }, //I'm sending filename as a param
    headers: { 'Authorization': $localStorage.jwt === undefined ? jwt : $localStorage.jwt },
    responseType: 'arraybuffer',
}).success(function (data, status, headers, config) {
    headers = headers();
    var filename = headers['x-filename'];
    var contentType = headers['content-type'];
    var linkElement = document.createElement('a');
    try {
        var blob = new Blob([data], { type: contentType });
        var url = window.URL.createObjectURL(blob);

        linkElement.setAttribute('href', url);
        linkElement.setAttribute("download", filename);

        var clickEvent = new MouseEvent("click", {
            "view": window,
            "bubbles": true,
            "cancelable": false
        });
        linkElement.dispatchEvent(clickEvent);
    } catch (ex) {
        console.log(ex);
    }
}).error(function (data, status, headers, config) {
}).finally(function () {

});

#1


30  

You don't necessarily need Ajax for this. Just an <a> link is enough if you set the content-disposition to attachment in the server side code. This way the parent page will just stay open, if that was your major concern (why would you unnecessarily have chosen Ajax for this otherwise?). Besides, there is no way to handle this nicely acynchronously. PDF is not character data. It's binary data. You can't do stuff like $(element).load(). You want to use completely new request for this. For that <a href="pdfservlet/filename.pdf">pdf</a> is perfectly suitable.

这并不需要Ajax。如果在服务器端代码中将内容配置设置为附件,那么只需一个链接就足够了。这样,如果这是您的主要关注点,那么父页面就会保持打开状态(否则为什么您会不必要地选择Ajax呢?)此外,也没有办法很好地处理这个问题。PDF不是字符数据。这是二进制数据。不能执行$(元素).load()之类的操作。您需要为此使用全新的请求。,< a href = " pdfservlet /文件名。pdf " > pdf < / >是完全合适的。

To assist you more with the server side code, you'll need to tell more about the language used and post an excerpt of the code attempts.

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

#2


103  

Here is how I got this working

这就是我的工作原理。

$.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();
  }
});

Updated answer using download.js

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

#3


29  

I don't really think that any of the past answers spotted out the problem of the original poster. They all presume a GET request while the poster was trying to POST data and get a download in response.

我真的不认为过去的任何一个答案发现了最初海报的问题。当海报试图发布数据并得到相应的下载时,他们都假定有一个GET请求。

In the course of searching for any better answer we found this jQuery Plugin for Requesting Ajax-like File Downloads.

在寻找更好答案的过程中,我们找到了这个jQuery插件,用于请求类似ajax的文件下载。

In its "heart" it creates a "temporary" HTML form containing the given data as input fields. This form is appended to the document and posted to the desired URL. Right after that the form is removed again:

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

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

Update Mayur's answer looks pretty promising and very simple in comparison to the jQuery plug-in I referred to.

与我提到的jQuery插件相比,Update Mayur的答案看起来非常有希望,而且非常简单。

#4


6  

This is how i solve this issue.
The answer of Jonathan Amend on this post helped me a lot.
The example below is simplified.

我就是这样解决这个问题的。乔纳森·阿蒙德在这篇文章中的回答对我帮助很大。

For more details, the above source code is able to download a file using a JQuery Ajax request (GET, POST, PUT etc). It, also, helps to upload parameters as JSON and to change the content type to application/json (my default).

要了解更多细节,上面的源代码可以使用JQuery Ajax请求(GET、POST、PUT等)下载文件。它还帮助将参数上传为JSON,并将内容类型更改为application/ JSON(我的默认值)。

The html source:

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>  

A simple form with two input text, one select and a button element.

一个包含两个输入文本、一个选择和一个按钮元素的简单表单。

The javascript page source:

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>  

A simple event on button click. It creates an AjaxDownloadFile object. The AjaxDownloadFile class source is below.

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

The AjaxDownloadFile class source:

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

I created this class to added to my JS library. It is reusable. Hope that helps.

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

#5


5  

You could use this plugin.

你可以使用这个插件。

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

This worked for me. Found this plugin here

这为我工作。发现这个插件

#6


4  

What worked for me is the following code, as the server function is retrieving File(memoryStream.GetBuffer(), "application/pdf", "fileName.pdf");:

为我工作的是下面的代码,因为服务器的功能是检索文件(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();
                }
});

#7


2  

create a hidden iframe, then in your ajax code above:

创建一个隐藏的iframe,然后在上面的ajax代码中:

url: document.getElementById('myiframeid').src = your_server_side_url,

url:. getelementbyid(“myiframeid”)。src = your_server_side_url,

and remove the window.open(response);

和删除window.open(响应);

#8


1  

Do you have to do it with Ajax? Coouldn't it be a possibility to load it in an iframe?

需要用Ajax实现吗?因为有可能把它装在iframe中吗?

#9


1  

Concerning the answer given by Mayur Padshala this is the correct logic to download a pdf file via ajax but as others report in the comments this solution is indeed downloads a blank pdf.

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

The reason for this is explained in the accepted answer of this question: jQuery has some issues loading binary data using AJAX requests, as it does not yet implement some HTML5 XHR v2 capabilities, see this enhancement request and this discussion.

原因在这个问题的公认答案中得到了解释:jQuery在使用AJAX请求加载二进制数据时遇到了一些问题,因为它还没有实现一些HTML5 XHR v2功能,请参见这个增强请求和这个讨论。

So using HTMLHTTPRequest the code should look like this:

使用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();
}

#10


0  

var xhr;
var beforeSend = function(){
    $('#pleasewaitDL').modal('show');
}
$(function () {
    $('#print_brochure_link').click(function(){
        beforeSend();
        xhr = new XMLHttpRequest();
        xhr.open("GET",$('#preparedPrintModalForm').attr('action'), true); 
        xhr.responseType = "blob";
        xhr.onload = function (e) {
            if (this.status === 200) {
                var file = window.URL.createObjectURL(this.response);
                var a = document.createElement("a");
                a.href = file;
                a.download = this.response.name || "Property Brochure";
                console.log(file);
                document.body.appendChild(a);
                a.click();
                
                window.onfocus = function () {                     
                  document.body.removeChild(a)
                }
                $('#pleasewaitDL').modal('hide');
            };
        };
        xhr.send($('#preparedPrintModalForm').serialize());
    });
    $('#pleasewaitDLCancel').click(function() {
        xhr.abort();
    });
});

#11


0  

If you have to work with file-stream (so no physically saved PDF) like we do and you want to download the PDF without page-reload, the following function works for us:

如果你必须像我们一样使用文件流(所以没有物理保存的PDF),并且你想下载PDF而不需要页面重新加载,下面的功能对我们是有效的:

HTML

HTML

<div id="download-helper-hidden-container" style="display:none">
     <form id="download-helper-form" target="pdf-download-output" method="post">
            <input type="hidden" name="downloadHelperTransferData" id="downloadHelperTransferData" />
     </form>
     <iframe id="pdf-helper-output" name="pdf-download-output"></iframe>
</div>

Javascript

Javascript

var form = document.getElementById('download-helper-form');
$("#downloadHelperTransferData").val(transferData);
form.action = "ServerSideFunctionWhichWritesPdfBytesToResponse";
form.submit();

Due to the target="pdf-download-output", the response is written into the iframe and therefore no page reload is executed, but the pdf-response-stream is output in the browser as a download.

由于目标=“pdf-download-output”,响应被写入iframe,因此不会执行页面重载,但是pdf-response-stream作为下载输出在浏览器中。

#12


0  

This snippet is for angular js users which will face the same problem, Note that the response file is downloaded using a programmed click event. In this case , the headers were sent by server containing filename and content/type.

这段代码是针对角js用户的,他们将面对同样的问题,注意到响应文件是通过一个程序的点击事件下载的。在这种情况下,头文件是由包含文件名和内容/类型的服务器发送的。

$http({
    method: 'POST', 
    url: 'DownloadAttachment_URL',
    data: { 'fileRef': 'filename.pdf' }, //I'm sending filename as a param
    headers: { 'Authorization': $localStorage.jwt === undefined ? jwt : $localStorage.jwt },
    responseType: 'arraybuffer',
}).success(function (data, status, headers, config) {
    headers = headers();
    var filename = headers['x-filename'];
    var contentType = headers['content-type'];
    var linkElement = document.createElement('a');
    try {
        var blob = new Blob([data], { type: contentType });
        var url = window.URL.createObjectURL(blob);

        linkElement.setAttribute('href', url);
        linkElement.setAttribute("download", filename);

        var clickEvent = new MouseEvent("click", {
            "view": window,
            "bubbles": true,
            "cancelable": false
        });
        linkElement.dispatchEvent(clickEvent);
    } catch (ex) {
        console.log(ex);
    }
}).error(function (data, status, headers, config) {
}).finally(function () {

});