web-dev-qa-db-ja.com

ajaxリクエストでブラウザにダウンロード

私は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ファイルには、PDF with FPDFライブラリ を作成するために次のものがあります:

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 <>streamx3Rðâ2Ð35W(çrQÐw3T04Ó30PISpêZ* [¤(hx¤æää+çå¤(j *dÔ7Wendstreamendobj10 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 <</Producer(FPDF 1.7)/ CreationDate(D:20150611094522 )> endobj 7 0 obj <</Type/Catalog/Pages 1 0 R> endobj xref 0 8 0000000000 65535 f 0000000228 00000 n 0000000416 00000 n 0000000009 00000 n 0000000087 00000 n 0000000315 00000 n 0000000520 00000 n 0000000595 00000nトレーラー<< /サイズ8 /ルート70 R /情報60 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を保存するためのダイアログが表示されません。私は何が間違っているのですか?

UPDATE 2

application-downloadapplication/pdfを変更しようとしました。彼はファイルをローカルに保存しますが、ダウンロードダイアログボックスが表示されません。

応答は次のようになります(Chromeでネットワークを確認すると):

%PDF-1.3 3 0 obj <> endobj 4 0 obj <>streamx3Rðâ2Ð35W(çrQÐw3T04Ó30PISpêZ* [¤(hx¤æää+çå¤(j *dÔ7Wendstreamendobj10 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 <</Producer(FPDF 1.7)/ CreationDate(D:20150617090832 )> endobj 7 0 obj <</Type/Catalog/Pages 1 0 R> endobj xref 0 8 0000000000 65535 f 0000000228 00000 n 0000000416 00000 n 0000000009 00000 n 0000000087 00000 n 0000000315 00000 n 0000000520 00000 n 0000000595 00000nトレーラー<< /サイズ8 /ルート70 R /情報60 R> startxref 644 %% EOF

33
nielsv

[〜#〜]更新[〜#〜]

FileSaver.jsを使用する方法も機能しません。JavaScriptのみを介してネイティブの[名前を付けて保存]ダイアログを強制的に呼び出す方法はないようです。例外はIEのsaveAsexecCommandだけです。チェック execCommand SaveAsは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 ポリフィルの場合

また、ブラウザにダウンロードプロセスをネイティブに処理させたくないため、Content-Disposition: attachmentヘッダーとContent-Type: application-downloadヘッダーを削除します。

これが動作するデモです http://plnkr.co/edit/9r1tehQ94t5vkqZfZuQC?p=preview 、PDFへのGETリクエストを示しています

6
Prayag Verma

私はあなたに一つのことを提案させてください。

AJAXのみ、ファイルをダウンロードすることはできません。最初にajax呼び出しで.Zipファイルを作成し、その後、そのファイルパスを取得して、任意のコマンドを使用してそのファイルを開く必要があります。

ここに私のために働く1つの例::)

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

確かに、それは動作します。一度お試しください。 :)

編集:

またはあなたは使用することができます

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

'abc.com/link':以下のコードを使用します:

  header("Content-type: application/octet-stream");
  header("Content-Disposition: attachment; filename=".$name);
  header("Pragma: no-cache");
  header("Expires: 0");
  readfile($file);
  exit;

ファイルはダウンロードリストにあります。

3
Ronak Patel
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デモ

2
Bogdan Kuštan

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でダウンロードされます。

2
Waqar

documentation によると、2番目のパラメータをDに設定できます。

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

保存したファイルを使用してすべての詳細を自分で処理したい場合は、次のようにして、PHPからダウンロードするためにPDFをブラウザーに提示しました。

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「HelloWorld!」を開いて含むダウンロード用:

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

?>
2
mike.k

これは(のみ)AJAXでは不可能です。

ここで使用できる主な手法は2つあり、どちらもJavaScriptを使用せずに実際のダウンロードを実行します。一般的な考え方は、目的のドキュメントを提供するリソースにブラウザをリダイレクトすることです。ダウンロードにリダイレクトする場合は、ページを離れず、代わりに[保存]ダイアログが表示されます。同様のトピックが この質問 で説明されています。

GETリクエスト

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応答を返すように、サーバーサイドスクリプトを調整します。

1
Ja͢ck