我正在尝试使用二进制流构建PDF文件,我将其作为Ajax请求的响应而收到。
通过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服务实现。所以它必须是客户端的解决方案。有什么想法吗?
答案 0 :(得分:22)
是否有任何解决方案,例如按顺序在文件系统上构建pdf文件 让用户下载它?
尝试将responseType
的{{1}}设置为XMLHttpRequest
,将blob
元素的download
属性替换为a
,以允许从window.open
下载响应{1}} XMLHttpRequest
文件
.pdf
答案 1 :(得分:12)
我意识到这是一个相当古老的问题,但这是我今天提出的解决方案:
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);
}
答案 2 :(得分:4)
我改变了这个:
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>';
它对我有用。
答案 3 :(得分:3)
我在PHP中工作并使用函数来解码从服务器发回的二进制数据。我将信息提取到一个简单的file.php输入,并通过我的服务器查看该文件,所有浏览器都显示pdf artefact。
<?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);
?>
答案 4 :(得分:2)
我最近在这个主题上看到了另一个问题(streaming pdf into iframe using dataurl only works in 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,然后创建了一个字符串,表示所需sie,id等的iframe的html,它使用构造的url作为src。一旦我将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或十六进制编码。我在pdf中的所有流上使用了flate,它运行良好。
答案 5 :(得分:2)
@alexandre和base64的答案可以解决问题。
解释为什么适用于IE的原因在这里
https://en.m.wikipedia.org/wiki/Data_URI_scheme
在标题'格式'下标明
某些浏览器(Chrome,Opera,Safari,Firefox)接受非标准版 如果两者都订购;提供base64和; charset,而Internet Explorer要求charset的规范必须先于 base64令牌。
答案 6 :(得分:2)
检测浏览器并使用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!
});
答案 7 :(得分:1)
You can use PDF.js to create PDF files from javascript... it's easy to code... hope this solve your doubt!!!
Regards!