Как создать 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.
У меня нет разрешения на редактирование реализации веб-сервиса. Так что это должно быть решение
на стороне клиента.
Любые идеи???
Ответы
Ответ 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!
});