使用ajax请求在浏览器中下载

时间:2015-06-11 09:48:29

标签: javascript php ajax angularjs fpdf

我正在使用AngularJS,我正在尝试在php中生成PDF。这就是我在 controller.js 中的内容:

$scope.downloadPDF = function(){
    $http.post('/download-pdf', { fid: $routeParams.fid })
        .success(function(data, status, headers, config){
            console.log("success");
        })
        .error(function(data, status, headers, config){
            console.log("error");
        });
};

在我的php文件中,我有以下内容来创建一个带有FPDF library的PDF:

function download_pdf()
{
    $id = $_POST['fid'];

    $pdf = new FPDF();

    $pdf->AddPage();
    $pdf->SetFont('Arial','B',16);
    $pdf->Cell(40,10,'Hello World!');

    header('Content-Type: application/pdf');
    header('Content-Disposition: attachment; filename=' . $id . '.pdf');

    $pdf->Output('Order123.pdf', 'D');
}

但请求是响应此而不是打开保存对话框来保存我的pdf。

  

%PDF-1.3       3 0 obj       <>       endobj       4 0 obj       <>       流       x3Rðâ2Ð35W(CR       QÐw3T04Ó30PISp           EZ * [¤(hx¤æää+çå¤(j *dÔ7W       endstream       endobj       1 0 obj       <       endobj       5 0 obj       <       endobj       2 0 obj       <<       / ProcSet [/ PDF / Text / ImageB / ImageC / ImageI]       / Font<<       / F1 5 0 R   >       / XObject<<   >   >       endobj       6 0 obj       <<       /制片人(FPDF 1.7)       / CreationDate(D:20150611094522)   >       endobj       7 0 obj       <<       /类型/目录       / Pages 1 0 R   >       endobj       外部参照       0 8       0000000000 65535 f       0000000228 00000       0000000416 00000       0000000009 00000       0000000087 00000       0000000315 00000       0000000520 00000       0000000595 00000       预告片       <<       /大小8       / Root 7 0 R       / Info 6 0 R   >       startxref       644       %% EOF

我使用了PHPExcel库,这很有效:

$objWriter = PHPExcel_IOFactory::createWriter($ea, 'Excel2007');

// We'll be outputting an excel file
header('Content-type: application/vnd.ms-excel');

// It will be called Submission on [date_now].xls
header('Content-Disposition: attachment; filename="' . $filename . '.xls' . '"');

// Write file to the browser
$objWriter->save('php://output');

现在我该如何为我的PDF工作?

更新

我编写了我的代码:

$pdf = new FPDF();

$pdf->AddPage();
$pdf->SetFont('Arial','B',16);
$pdf->Cell(40,10,'Hello World!');

$filename = DXS_VKGROUP_PLUGIN_LIB_DIR . 'uploads/' . $_POST['fid'] . '.pdf';

$pdf->Output($filename, 'F'); // Save file locally

header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Type: application-download');
header('Content-Length: ' . filesize($filename));
header('Content-Transfer-Encoding: binary');
header('Content-Disposition: attachment; filename="' . $filename . '"');

$handle = fopen($filename, 'rb');
fpassthru($handle);
fclose($handle);

文件在本地保存,但下载不起作用。它没有得到我保存pdf的对话框。我做错了什么?

更新2

我现在尝试更改application-download中的application/pdf。他在本地保存文件但我没有下载对话框。

响应如下(当我在Chrome中检查网络时):

  

%PDF-1.3       3 0 obj       <>       endobj       4 0 obj       <>       流       x3Rðâ2Ð35W(CR       QÐw3T04Ó30PISp           EZ * [¤(hx¤æää+çå¤(j *dÔ7W       endstream       endobj       1 0 obj       <       endobj       5 0 obj       <       endobj       2 0 obj       <<       / ProcSet [/ PDF / Text / ImageB / ImageC / ImageI]       / Font<<       / F1 5 0 R   >       / XObject<<   >   >       endobj       6 0 obj       <<       /制片人(FPDF 1.7)       / CreationDate(D:20150617090832)   >       endobj       7 0 obj       <<       /类型/目录       / Pages 1 0 R   >       endobj       外部参照       0 8       0000000000 65535 f       0000000228 00000       0000000416 00000       0000000009 00000       0000000087 00000       0000000315 00000       0000000520 00000       0000000595 00000       预告片       <<       /大小8       / Root 7 0 R       / Info 6 0 R   >       startxref       644       %% EOF

8 个答案:

答案 0 :(得分:6)

更新

使用FileSaver.js的方法也不起作用,似乎没有办法仅通过JavaScript强制调用本机另存为对话框,只有异常是IE的saveAs execCommand。查看Does execCommand SaveAs work in Firefox?

在项目中包含FileSaver.js作为依赖项

按如下所示更改downloadPDF功能

 $scope.downloadPDF = function() {
    $http.post('/download-pdf', {
        fid: $routeParams.fid
      }, {
        responseType: 'arraybuffer'
      })
      .success(function(data, status, headers, config) {
        // Convert response data to Blob
        var file = new Blob([data], {
          type: 'application/pdf'
        });
        // Call the File Saver method to save the above Blob,this will show Save As dialog
        saveAs(file, "test.pdf");
      })
      .error(function(data, status, headers, config) {
        console.log("error");
      });

 };

Blob对象适用于大多数现代浏览器,但对IE的支持有限。 10,检查https://github.com/eligrey/FileSaver.js#supported-browsers是否有polyfills

同时删除Content-Disposition: attachmentContent-Type: application-download标题,因为我们不希望浏览器本地处理下载过程

这是一个有效的演示http://plnkr.co/edit/9r1tehQ94t5vkqZfZuQC?p=preview,它显示了对PDF的GET请求

答案 1 :(得分:3)

让我建议你一件事。

通过AJAX,您无法下载任何文件。 您需要首先使用ajax调用创建.zip文件,然后获取该文件路径后,您必须使用任何命令打开该文件。

这里有一个适合我的例子::)

            border: 1px solid;
            border-color: #bd362f #bd362f #802420;

当然,它有效。试试一次。 :)

修改

或者您可以使用

$http.post('www.abc.com/zipcreate', {'id': id}).then(function (zipurl) {
                    $window.location = zipurl;
            });
'abc.com/link'中的

使用下面的代码:

$window.location = 'abc.com/link';

您将获得下载列表中的文件。

答案 2 :(得分:2)

根据documentation,您可以将第二个参数设置为D

$pdf->Output('Order123.pdf', 'D');

如果您想使用保存的文件自行处理所有细节,我就是这样将PDF呈现给浏览器以便从PHP下载:

header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Type: application-download');
header('Content-Length: ' . filesize('file.pdf'));
header('Content-Transfer-Encoding: binary');
header('Content-Disposition: attachment; filename="file.pdf"');
$handle = fopen('file.pdf', 'rb');
fpassthru($handle);
fclose($handle);

更新

请确认PDF文件确实正在制作中。 Web服务器进程是否具有该路径的写访问权限? FPDF是否正确包含在内?我在一个测试VM上创建了它,它提供了一个文件1.pdf供下载,它打开并包含“Hello World!”:

<?php

require('/var/www/html/fpdf17/fpdf.php');

$_POST = array('fid' => '1');

$pdf = new FPDF();

$pdf->AddPage();
$pdf->SetFont('Arial', 'B', 16);
$pdf->Cell(40, 10, 'Hello World!');

$filename = '/tmp/' . $_POST['fid'] . '.pdf';

$pdf->Output($filename, 'F'); // Save file locally

header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Type: application-download');
header('Content-Length: ' . filesize($filename));
header('Content-Transfer-Encoding: binary');
header('Content-Disposition: attachment; filename="' . basename($filename) . '"');

$handle = fopen($filename, 'rb');
fpassthru($handle);
fclose($handle);

unlink($filename);

?>

答案 3 :(得分:2)

使用ajax是不可能的。
相反,你可以做的是,通过javascript表单提交命中你的行动。

例如,document.getElementById(formID).action= actionName

document.getElementById(formID).submit();  

此处,formID是您表单的ID,actionName将是'/download-pdf',如您所指定的那样。

在您的操作类中 - 设置响应标头

getResponse().setContentType("application/pdf");
getResponse().setHeader("Content-Disposition",  " attachment; filename= "+"pdffile.pdf");

这将导致您的文件以filename = pdffile.pdf下载。

答案 4 :(得分:2)

header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"" . basename($file_url) . "\"");

或者使用BLOB:

 $scope.downloadPDF = function() {
    $http.post('/download-pdf', {
        fid: $routeParams.fid
      }, {
        responseType: 'arraybuffer'
      })
      .success(function(data, status, headers, config) {

        var file = new Blob([data], {
          type: 'application/pdf'
        });
        var url = URL.createObjectURL(blob);
        window.location.href = url;
      })
      .error(function(data, status, headers, config) {
        console.log("error");
      });

 };

或创建一个download属性的元素:

$scope.downloadPDF = function() {
    $http.get('http://46.101.139.188/demo.pdf', {
      }, {
        responseType: 'arraybuffer'
      })
      .success(function(data, status, headers, config) {

        var file = new Blob([data], {
          type: 'application/pdf'
        });
        var url = URL.createObjectURL(file);
        var a = document.createElement('a');
        a.setAttribute('download', 'download');
        a.setAttribute('href', url);

         var event = new MouseEvent('click', {
          'view': window,
          'bubbles': true,
          'cancelable': true
        });
        a.dispatchEvent(event);
      })
      .error(function(data, status, headers, config) {
        console.log("error");
      });
 };

plnkr demo

答案 5 :(得分:1)

这是(仅)AJAX无法实现的。

您可以在这里使用两种主要技术,不使用使用JavaScript执行实际下载。一般的想法是您将浏览器重定向到将提供所需文档的资源;如果您重定向到下载,它将不会离开页面,而是显示“保存”对话框。 this question中讨论了类似的主题。

获取请求

location.href = '/download-pdf?fid=' + encodeURIComponent($routeParams.fid);

调整服务器端脚本以使用$_GET['fid']

POST请求

服务器创建资源并使用可以找到资源的URL进行响应:

$http.post('/download-pdf', { fid: $routeParams.fid })
    .success(function(data, status, headers, config) {
        // follow location provided by server
        location.href = data.redirect_url;
        console.log("success");
    })
    .error(function(data, status, headers, config){
        console.log("error");
    });

调整服务器端脚本,以在创建新资源后返回适当的JSON响应。

答案 6 :(得分:0)

我以以下方式进行操作,对我来说效果很好:

$(document).ready(function () {
            $('#generaPdf').click(function (e) {
            e.preventDefault();
            var name = $('#name').val();
            $.ajax
                ({
                    type: "POST",
                    url: "pdf.php",
                    data: { "name": name },
                    success: function (data) {
                        alert("todo ok")
                        location.href = "pdf.php"
                        // $('.result').html(data);
                        // $('#contactform')[0].reset();
                    }
                });
            });
        });

我的html:

<button type="submit" class="btn btn-primary" id="generaPdf"><i class="fas fa-link"></i> Generar documento para impresión</button>

答案 7 :(得分:-1)

将文档发送到给定目标:浏览器,文件或字符串。在浏览器的情况下,可以使用插件(如果存在)或强制下载(&#34;另存为&#34;对话框)。

如果需要,方法首先调用Close()来终止文档。

<强>参数

名称:

文件的名称。如果未指定,则文档将以名称doc.pdf发送到浏览器(目标I)。

<强> DEST

目的地发送文件的位置。它可以采用以下值之一:

  • 我:将文件内联发送到浏览器。如果使用插件 可用。当选择&#34;保存时,使用名称给出的名称 作为&#34;生成PDF的链接上的选项。
  • D:发送到浏览器并强制下载给定名称的文件 按名字。
  • F:保存到名称为name的本地文件(可能 包括路径)。
  • S:将文档作为字符串返回。名称被忽略。