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

Как создать PDF файл из двоичной строки, возвращаемой с веб-службы, используя javascript

Я пытаюсь создать PDF файл из двоичного потока, который я получаю в ответ от запроса ajax.

Через XmlHttpRequest я получаю следующие данные:

%PDF-1.4....
.....
....hole data representing the file
....
%% EOF

То, что я пробовал до сих пор, заключалось в том, чтобы вставлять свои данные через данные: uri.

Теперь нет ничего плохого в этом. Он работает нормально. К сожалению, он не работает в IE9 и FF.

Возможная причина может заключаться в том, что у FF и IE9 есть проблемы с этим использованием данных-uri.

Теперь я ищу любое решение, которое работает для всех браузеров.

Здесь мой код:

// responseText encoding 
pdfText=$.base64.decode($.trim(pdfText));

// Now pdfText contains %PDF-1.4 ...... data...... %%EOF

var winlogicalname = "detailPDF";
var winparams = 'dependent=yes,locationbar=no,scrollbars=yes,menubar=yes,'+
            'resizable,screenX=50,screenY=50,width=850,height=1050';

var htmlText = '<embed width=100% height=100%'
                     + ' type="application/pdf"'
                     + ' src="data:application/pdf,'
                     + escape(pdfText)
                     + '"></embed>'; 

                // Open PDF in new browser window
                var detailWindow = window.open ("", winlogicalname, winparams);
                detailWindow.document.write (htmlText);
                detailWindow.document.close ();

Как я уже сказал, он отлично работает для Opera и Chrome (Safari не тестировался). Использование IE или FF откроет пустое новое окно.

Есть ли какое-либо решение, например, создание файла pdf в файловой системе чтобы пользователь мог его загрузить?

Мне нужно решение, которое работает во всех браузерах по крайней мере, в IE, FF, Opera, Chrome и Safari.

У меня нет разрешения на редактирование реализации веб-сервиса. Так что это должно быть решение на стороне клиента.

Любые идеи???

4b9b3361

Ответ 1

Есть ли какое-либо решение, например, создание файла pdf в файловой системе для упорядочения чтобы пользователь мог загрузить его?

Попробуйте установить responseType от XMLHttpRequest до blob, заменив атрибут download на элемент a для window.open, чтобы разрешить загрузку ответа из XMLHttpRequest в качестве .pdf файла

var request = new XMLHttpRequest();
request.open("GET", "/path/to/pdf", true); 
request.responseType = "blob";
request.onload = function (e) {
    if (this.status === 200) {
        // `blob` response
        console.log(this.response);
        // create `objectURL` of `this.response` : `.pdf` as `Blob`
        var file = window.URL.createObjectURL(this.response);
        var a = document.createElement("a");
        a.href = file;
        a.download = this.response.name || "detailPDF";
        document.body.appendChild(a);
        a.click();
        // remove `a` following `Save As` dialog, 
        // `window` regains `focus`
        window.onfocus = function () {                     
          document.body.removeChild(a)
        }
    };
};
request.send();

Ответ 2

Я понимаю, что это довольно старый вопрос, но вот решение, которое я придумал сегодня:

doSomethingToRequestData().then(function(downloadedFile) {
  // create a download anchor tag
  var downloadLink      = document.createElement('a');
  downloadLink.target   = '_blank';
  downloadLink.download = 'name_to_give_saved_file.pdf';

  // convert downloaded data to a Blob
  var blob = new Blob([downloadedFile.data], { type: 'application/pdf' });

  // create an object URL from the Blob
  var URL = window.URL || window.webkitURL;
  var downloadUrl = URL.createObjectURL(blob);

  // set object URL as the anchor href
  downloadLink.href = downloadUrl;

  // append the anchor to document body
  document.body.append(downloadLink);

  // fire a click event on the anchor
  downloadLink.click();

  // cleanup: remove element and revoke object URL
  document.body.removeChild(downloadLink);
  URL.revokeObjectURL(downloadUrl);
}

Ответ 3

Я изменил это:

var htmlText = '<embed width=100% height=100%'
                 + ' type="application/pdf"'
                 + ' src="data:application/pdf,'
                 + escape(pdfText)
                 + '"></embed>'; 

к

var htmlText = '<embed width=100% height=100%'
                 + ' type="application/pdf"'
                 + ' src="data:application/pdf;base64,'
                 + escape(pdfText)
                 + '"></embed>'; 

и это сработало для меня.

Ответ 4

Я работаю на PHP и использую функцию для декодирования двоичных данных, отправленных с сервера. Я извлекаю информацию для ввода в файл file.php и просматриваю файл через мой сервер, и все браузеры отображают файл pdf.

<?php
   $data = 'dfjhdfjhdfjhdfjhjhdfjhdfjhdfjhdfdfjhdf==blah...blah...blah..'

   $data = base64_decode($data);
    header("Content-type: application/pdf");
    header("Content-Length:" . strlen($data ));
    header("Content-Disposition: inline; filename=label.pdf");
    print $data;
    exit(1);

?>

Ответ 5

Я недавно увидел другой вопрос только по этой теме (потоковая передача в iframe с использованием dataurl работает только в chrome).

Я создал pdf файлы в ast и передал их в браузер. Я создавал их сначала с помощью fdf, затем с классом pdf, который я написал сам - в каждом случае pdf был создан из данных, полученных из COM-объекта, на основе пары параметров GET, переданных через URL-адрес.

От взгляда на ваши данные, полученные в результате вызова ajax, похоже, что вы почти там. Я не играл с кодом уже пару лет и не документировал его так же хорошо, как я бы позаботился, но... я думаю, что все, что вам нужно сделать, это установить цель iframe как URL-адрес вы получаете pdf файл. Хотя это может не сработать - файл, который выводит pdf, также может сначала вывести заголовок ответа html.

Вкратце, это код вывода, который я использовал:

//We send to a browser
header('Content-Type: application/pdf');
if(headers_sent())
    $this->Error('Some data has already been output, can\'t send PDF file');
header('Content-Length: '.strlen($this->buffer));
header('Content-Disposition: inline; filename="'.$name.'"');
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
ini_set('zlib.output_compression','0');
echo $this->buffer;

Итак, не видя полного текста ответа на вызов ajax, я не могу быть уверенным, что это такое, хотя я склонен думать, что код, который выводит запрашиваемый pdf файл, может быть только doig эквивалентным последней строки в приведенном выше коде. Если у вас есть код, которым вы управляете, я бы попытался установить заголовки - тогда браузер может просто обработать текст ответа - вам не нужно беспокоиться о том, чтобы что-то делать с ним.

Я просто построил url для pdf, который я хотел (расписание), затем создал строку, которая представляла html для iframe желаемого sie, id и т.д., который использовал построенный url как src. Как только я установил внутренний html div в построенную строку html, браузер попросил PDF, а затем отобразил его, когда он был получен.

function  showPdfTt(studentId)
{
    var url, tgt;
    title = byId("popupTitle");
    title.innerHTML = "Timetable for " + studentId;
    tgt = byId("popupContent");
    url = "pdftimetable.php?";
    url += "id="+studentId;
    url += "&type=Student";
    tgt.innerHTML = "<iframe onload=\"centerElem(byId('box'))\" src='"+url+"' width=\"700px\" height=\"500px\"></iframe>";
}

EDIT: забыл упомянуть - вы можете отправить бинарный PDF таким образом. Потоки, которые они содержат, не обязательно должны быть ascii85 или шестнадцатеричным. Я использовал flate во всех потоках в pdf, и он работал нормально.

Ответ 6

Ответ @alexandre на base64 делает трюк.

Объяснение, почему это работает для IE, здесь

https://en.m.wikipedia.org/wiki/Data_URI_scheme

В заголовке 'format', где говорится

Некоторые браузеры (Chrome, Opera, Safari, Firefox) принимают нестандартные заказывая, если поставляются оба: base64 и; charset, в то время как Интернет Explorer требует, чтобы спецификация кодировки должна предшествовать base64.

Ответ 7

Вы можете использовать PDF.js для создания PDF файлов из javascript... это легко кодировать... надеюсь, что это решит ваши сомнения!!!

Привет!

Ответ 8

Обнаружение браузера и использование URI-данных для Chrome и использование PDF.js, как показано ниже для других браузеров.

PDFJS.getDocument(url_of_pdf)
.then(function(pdf) {
    return pdf.getPage(1);
})
.then(function(page) {
    // get a viewport
    var scale = 1.5;
    var viewport = page.getViewport(scale);
    // get or create a canvas
    var canvas = ...;
    canvas.width = viewport.width;
    canvas.height = viewport.height;

    // render a page
    page.render({
        canvasContext: canvas.getContext('2d'),
        viewport: viewport
    });
})
.catch(function(err) {
    // deal with errors here!
});