使用 JavaScript 在客户端将 base64 字符串保存为 PDF

Posted

技术标签:

【中文标题】使用 JavaScript 在客户端将 base64 字符串保存为 PDF【英文标题】:Save base64 string as PDF at client side with JavaScript 【发布时间】:2012-07-10 01:38:19 【问题描述】:

所以我的问题是:我有一个 pdf 文件作为我从服务器获取的 base64 字符串。我想使用此字符串将 PDF 直接显示到浏览器,或者在单击链接时为其提供“另存为...”选项。这是我正在使用的代码:

<!doctype>
<html>
<head>
   <title>jsPDF</title>
   <script type="text/javascript" src="../libs/base64.js"></script>
   <script type="text/javascript" src="../libs/sprintf.js"></script>
   <script type="text/javascript" src="../jspdf.js"></script>

       <script type="text/javascript">

        function demo1() 
            jsPDF.init();
            jsPDF.addPage();
            jsPDF.text(20, 20, 'Hello world!');
            jsPDF.text(20, 30, 'This is client-side Javascript, pumping out a PDF.');

            // Making Data URI
            var out = jsPDF.output();
            var url = 'data:application/pdf;base64,' + Base64.encode(out);

            document.location.href = url;
         
    </script>
</head>
<body>

<a href="javascript:demo1()">Run Code</a>

</body>
</html>

它在 Chrome 和 Safari 上运行良好。 Firefox 确实识别 pdf,但不显示它,因为 FF 需要存在扩展名,但在这种情况下 data-URI 没有。我在这里坚持的原因,如果 chrome 和 safari 让它工作,那么必须有 FF 和 IE 的解决方案

我知道有一些相关的问题,但不是确切的问题,现在也有点老了。我知道一种解决方法是在服务器端生成 pdf,但我想在客户端生成它。

所以请聪明的人,是否有可能通过一些黑客或额外的 JS 下载插件?

【问题讨论】:

你好???有没有人对这个问题有一些答案..可能是约翰·雷西格 ;-) @owsata,同样的问题!它只是打开窗口!你找到解决问题的方法了吗?请告诉我们。谢谢 @FabioMilheiro Nope 没有发现任何有用的东西。最终的结果是,因为浏览器处理数据:应用程序的想法不同,所以一开始并没有太多使用它。所以最后的手段->从服务器发送现成的pdf。 Saving Base64 encoded PDF with Internet Explorer 10 and below的可能重复 ***.com/a/16245768/7282741 这个解决了我的问题并节省了我的周末。 【参考方案1】:

您可以创建如下所示的锚点来下载 base64 pdf:

<a download=pdfTitle href=pdfData title='Download pdf document' />

其中的 pdfData 强>是base64编码的PDF等的 “数据:应用/ PDF; BASE64,JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBSL0ZpbHRlci9GbGF0ZURlY29kZT4 + CnN0cmVhbQp4nO1cyY4ktxG911fUWUC3kjsTaBTQ1Ytg32QN4IPgk23JMDQ2LB / 0 + 2YsZAQzmZk1PSPIEB ...” P>

【讨论】:

你的这些信息帮助我在 Salesforce Lightning 中完成了它,使用这个字符串你可以在按钮点击时进行文件下载 在 C# 中,当您返回 FileContentResult 时,它会保留以 base64 编码的文件,但是没有任何迹象表明它也没有 mime 类型。所以为了在客户端正确实现它,我必须附加数据:应用程序/pdf;base64,在字符串前面,它起作用了! 这帮助我避免为了下载文件而创建额外的后端端点,谢谢!! @OssSilva 很高兴听到这个消息!【参考方案2】:

您可以使用此功能从 base64 下载文件。

function downloadPDF(pdf) 
const linkSource = `data:application/pdf;base64,$pdf`;
const downloadLink = document.createElement("a");
const fileName = "abc.pdf";
downloadLink.href = linkSource;
downloadLink.download = fileName;
downloadLink.click();

此代码将使用 href 和下载文件制作一个锚标记。如果你想使用按钮,那么你可以在你的按钮点击时调用点击方法。

希望对你有帮助,谢谢

【讨论】:

【参考方案3】:

您应该可以使用下载文件

window.open("data:application/pdf;base64," + Base64.encode(out));

【讨论】:

不,Chrome 和 FF 直接下载但不分配扩展名。 Safari 打开 PDF 并在浏览器中显示它哇。 IE 会打开一个标题为“application/octet-stream”的新标签页,仅此而已... 我使用数据结构进行了直接重定向,但是它需要一个容器或一种机制来将数据解析为可用的格式(例如:iFrame)。然而,我还没有按照规定测试这种机制。【参考方案4】:

我知道这个问题很老,但也想完成这个并在寻找时遇到了它。对于 Internet Explorer,我使用来自 here 的代码来保存 Blob。要从 base64 字符串创建一个 blob,这个网站上有很多结果,所以它不是我的代码,我只是不记得具体的来源:

function b64toBlob(b64Data, contentType) 
    contentType = contentType || '';
    var sliceSize = 512;
    b64Data = b64Data.replace(/^[^,]+,/, '');
    b64Data = b64Data.replace(/\s/g, '');
    var byteCharacters = window.atob(b64Data);
    var byteArrays = [];

    for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) 
        var slice = byteCharacters.slice(offset, offset + sliceSize);

        var byteNumbers = new Array(slice.length);
        for (var i = 0; i < slice.length; i++) 
            byteNumbers[i] = slice.charCodeAt(i);
        

        var byteArray = new Uint8Array(byteNumbers);

        byteArrays.push(byteArray);
    

    var blob = new Blob(byteArrays, type: contentType);
    return blob;

使用链接文件保护程序:

if (window.saveAs)  window.saveAs(blob, name); 
    else  navigator.saveBlob(blob, name); 

【讨论】:

文件保护程序在 Safari 中也失败了 :( 我在此链接***.com/questions/34436133/… 上发布了解决方案,该解决方案在 IE、CHROME、FF 中运行良好。如果此解决方案对您有帮助,请尝试投票【参考方案5】:

dataURItoBlob(dataURI) 
      const byteString = window.atob(dataURI);
      const arrayBuffer = new ArrayBuffer(byteString.length);
      const int8Array = new Uint8Array(arrayBuffer);
      for (let i = 0; i < byteString.length; i++) 
        int8Array[i] = byteString.charCodeAt(i);
      
      const blob = new Blob([int8Array],  type: 'application/pdf');
      return blob;
    

// data should be your response data in base64 format

const blob = this.dataURItoBlob(data);
const url = URL.createObjectURL(blob);

// to open the PDF in a new window
window.open(url, '_blank');

【讨论】:

我在网上找了几个解决方案,只有这个对我有用,谢谢 Manas Sahu 先生 我很高兴@RicardoLerma。【参考方案6】:

您不需要任何库。 JavaScript 已经支持这一点。这是我的端到端解决方案。

const xhr = new XMLHttpRequest();
xhr.open('GET', 'your-end-point', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
xhr.responseType = 'blob';
xhr.onreadystatechange = function () 
    if (this.readyState == 4 && this.status == 200) 
       if (window.navigator.msSaveOrOpenBlob) 
           window.navigator.msSaveBlob(this.response, "fileName.pdf");
         else 
           const downloadLink = window.document.createElement('a');
           const contentTypeHeader = xhr.getResponseHeader("Content-Type");
           downloadLink.href = window.URL.createObjectURL(new Blob([this.response],  type: contentTypeHeader ));
           downloadLink.download = "fileName.pdf";
           document.body.appendChild(downloadLink);
           downloadLink.click();
           document.body.removeChild(downloadLink);
        
    
;
xhr.send(null);

这也适用于 .xls.zip 文件。您只需将文件名更改为fileName.xlsfileName.zip。这取决于您的情况。

【讨论】:

以上是关于使用 JavaScript 在客户端将 base64 字符串保存为 PDF的主要内容,如果未能解决你的问题,请参考以下文章

如何将JavaScript数组信息导出到csv(在客户端)?

使用 JavaScript 在客户端将 base64 字符串保存为 PDF

typescript 对于博客 - 使用systemjs将Phoenix javascript客户端包含在Angular 2应用程序中

如何使用 Cordova 应用程序将 base64 图像保存到设备中?

HTML之Data URL(转)

我想在成功将数据插入数据库后为客户端显示消息..那么如何在javascript中使用alert()消息来实现这一点?