Подтвердить что ты не робот

Загрузить в браузере с помощью ajax request

Я работаю с AngularJS, и я пытаюсь создать PDF файл в php. Это то, что у меня есть в моем контроллере .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 файл с библиотекой 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     < >     поток     x3Rðâ2Ð35W (Сr     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 <     /F 1 5 0 R >     /XObject < →     endobj     6 0 obj     & Л; <     /Производитель (FPDF 1.7)     /CreationDate (D: 20150611094522) >     endobj     7 0 obj     & Л; <     /Тип/Каталог     /Страницы 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 00000 n     прицеп     & Л; <     /Размер 8     /Корень 7 0 R     /Инфо 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?

UPDATE:

Я редактировал свой код:

$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 (Сr     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 <     /F 1 5 0 R >     /XObject < →     endobj     6 0 obj     & Л; <     /Производитель (FPDF 1.7)     /CreationDate (D: 20150617090832) >     endobj     7 0 obj     & Л; <     /Тип/Каталог     /Страницы 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 00000 n     прицеп     & Л; <     /Размер 8     /Корень 7 0 R     /Инфо 6 0 R >     startxref     644     %% EOF

4b9b3361

Ответ 1

ОБНОВЛЕНИЕ

Метод использования FileSaver.js также не работает, похоже, не существует способа принудительно вызвать собственный диалог "Сохранить как" с помощью JavaScript, но единственным исключением является saveAs execCommand для IE. Проверить Работает ли 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 для polyfills

Также удалите заголовки Content-Disposition: attachment и Content-Type: application-download, так как мы не хотим, чтобы браузер обрабатывал процесс загрузки

Вот рабочая демонстрация http://plnkr.co/edit/9r1tehQ94t5vkqZfZuQC?p=preview, она показывает запрос GET для PDF

Ответ 2

Позвольте мне предложить вам одну вещь.

Только AJAX вы не можете скачать любой файл. Вам нужно сначала создать ZIP файл с помощью ajax-вызова, и после этого, получив этот путь к файлу, вы должны открыть этот файл с помощью любой команды.

Вот один пример, который работает для меня::)

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

Конечно, это работает. Попробуйте один раз.:)

EDIT:

Или вы можете использовать

$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

В соответствии с документацией вы можете установить второй параметр 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);

Update:

Убедитесь, что файл PDF действительно выполнен. Имеет ли процесс веб-сервера доступ на запись к этому пути? Правильно ли включен FPDF? Я сделал это на тестовой виртуальной машине и представил файл 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);

?>

Ответ 4

С ajax это невозможно.
Вместо этого вы можете сделать это, нажав ваше действие через форму javascript.

например, document.getElementById(formID).action= actionName.

document.getElementById(formID).submit();  

Здесь formID - это ваш идентификатор формы, а actionName будет '/download-pdf', как вы указали.

В вашем классе действий - установите заголовки ответов

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

Это приведет к загрузке файла с именем файла = pdffile.pdf.

Ответ 5

Это невозможно с (только) AJAX.

Существует два основных метода, которые вы можете использовать здесь: оба без использования JavaScript для фактической загрузки. Общая идея заключается в том, что вы перенаправляете браузер на ресурс, который предоставит желаемый документ; если вы перенаправляетесь на скачивание, он не покидает страницу, но вместо этого отображает диалог "Сохранить". Аналогичная тема обсуждается в этом вопросе.

Запрос GET

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

Откорректируйте серверную сторону script для использования $_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");
    });

Отрегулируйте серверную сторону script, чтобы вернуть соответствующий ответ JSON после создания нового ресурса.

Ответ 6

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

Ответ 7

Отправьте документ в указанное место назначения: браузер, файл или строка. В случае браузера можно использовать подключаемый модуль (если он есть) или загрузить (диалоговое окно "Сохранить как" ).

Сначала метод вызывает Close(), чтобы завершить документ.

Параметры

имя:

Имя файла. Если не указано, документ будет отправлен в браузер (пункт назначения I) с именем doc.pdf.

Dest

Назначение, куда отправить документ. Он может принимать одно из следующих значений:

  • I: отправьте файл встроенным в браузер. Плагин используется, если доступный. Имя, указанное именем, используется, когда вы выбираете "Сохранить как "на ссылке, генерирующей PDF.
  • D: отправить в браузер и принудительно загрузить файл с указанным именем по имени.
  • F: сохранить в локальный файл с именем, указанным по имени (может укажите путь).
  • S: возвращает документ как строку. имя игнорируется.