Ajaxリクエストからの応答として受け取るバイナリストリームからPDFファイルを作成しようとしています。
XmlHttpRequest
経由で、次のデータを受け取ります。
%PDF-1.4....
.....
....hole data representing the file
....
%% EOF
これまで試したのは、data:uri
経由でデータを埋め込むことでした。今、それは何の問題もありませんし、うまく動作します。残念ながら、IE9およびFirefoxでは機能しません。考えられる理由は、FFとIE9がdata-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。
Webサービスの実装を編集する権限がありません。そのため、クライアント側でソリューションにする必要がありました。何か案は?
ユーザーがダウンロードできるように、ファイルシステムにPDFファイルを作成するような解決策はありますか?
responseType
のXMLHttpRequest
をblob
に設定して、download
からの応答のダウンロードを許可するためにa
要素のXMLHttpRequest
属性をwindow.open
に置き換えてください。 _ as .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();
これはかなり古い質問であることがわかりますが、今日私が思いついた解決策は次のとおりです。
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's 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);
}
これを変更しました:
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>';
そしてそれは私のために働いた。
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);
?>
ブラウザを検出し、ChromeにData-URIを使用し、他のブラウザには以下のように 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!
});
最近、このトピックに関する別の質問を見ました( dataurlを使用してPDFをiframeにストリーミングすると、chromeでのみ機能します )。
AstでPDFを作成し、ブラウザにストリーミングしました。最初にfdfで作成し、次に自分で作成したpdfクラスで作成しました。それぞれの場合、pdfは、URLを介して渡されたいくつかのGETパラメーターに基づいてCOMオブジェクトから取得したデータから作成されました。
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を出力するコードは最後のものに相当するだけだと思う傾向があります上記のコードの行。あなたが制御できるコードであれば、ヘッダーを設定してみます-そうすれば、ブラウザーは応答テキストを処理するだけで済みます-わざわざそれをする必要はありません。
必要なpdf(タイムテーブル)のURLを作成し、作成したURLをsrcとして使用する目的のsie、idなどのiframeのhtmlを表す文字列を作成しました。 divの内部htmlを作成された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>";
}
編集:言及するのを忘れた-あなたはこの方法でバイナリPDFを送信することができます。それらに含まれるストリームは、ascii85または16進エンコードである必要はありません。 PDFのすべてのストリームでflateを使用しましたが、正常に機能しました。
Base64での@alexandreの答えがそのトリックです。
IEで機能する理由の説明はこちら
https://en.m.wikipedia.org/wiki/Data_URI_scheme
ヘッダー「フォーマット」の下には
一部のブラウザー(Chrome、Opera、Safari、Firefox)は、; base64と; charsetの両方が指定されている場合、非標準の順序を受け入れますが、Internet Explorerでは、charsetの仕様がbase64トークンよりも前にある必要があります。
PDF.js を使用して、JavaScriptからPDFファイルを作成できます...コーディングは簡単です...これがあなたの疑問を解決することを願っています!!!
よろしく!