7

我正在从 base64 字符串嵌入 PDF,如下所示:

var pdfData = 'data:application/pdf;filename=MY_CUSTOM_FILENAME.pdf;base64,' +
  'JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwog' +
  'IC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAv' +
  'TWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0K' +
  'Pj4KZW5kb2JqCgozIDAgb2JqCjw8CiAgL1R5cGUgL1BhZ2UKICAvUGFyZW50IDIgMCBSCiAg' +
  'L1Jlc291cmNlcyA8PAogICAgL0ZvbnQgPDwKICAgICAgL0YxIDQgMCBSIAogICAgPj4KICA+' +
  'PgogIC9Db250ZW50cyA1IDAgUgo+PgplbmRvYmoKCjQgMCBvYmoKPDwKICAvVHlwZSAvRm9u' +
  'dAogIC9TdWJ0eXBlIC9UeXBlMQogIC9CYXNlRm9udCAvVGltZXMtUm9tYW4KPj4KZW5kb2Jq' +
  'Cgo1IDAgb2JqICAlIHBhZ2UgY29udGVudAo8PAogIC9MZW5ndGggNDQKPj4Kc3RyZWFtCkJU' +
  'CjcwIDUwIFRECi9GMSAxMiBUZgooSGVsbG8sIHdvcmxkISkgVGoKRVQKZW5kc3RyZWFtCmVu' +
  'ZG9iagoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDEwIDAwMDAwIG4g' +
  'CjAwMDAwMDAwNzkgMDAwMDAgbiAKMDAwMDAwMDE3MyAwMDAwMCBuIAowMDAwMDAwMzAxIDAw' +
  'MDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9v' +
  'dCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G';

function loadPdf() {
  var pdf= document.querySelector('.pdf')

  var pobj = document.createElement('object')
  pobj.className= "pdf_object"
  pobj.setAttribute('data', pdfData)
  pobj.setAttribute('type', 'application/pdf')

  pdf.appendChild(pobj)
} 
.pdf_object {
  width: 100%;
  height: 700px;  
}
<div>
  <button onclick="loadPdf();">
    CLICK TO LOAD BELOW THE PDF
  </button>
</div>
<div class="pdf"></div>

这适用于 Firefox 和 Chrome。

我的问题是我无法自定义 pdf 下载操作的文件名。请注意,我使用的是filename参数 ( 'data:application/pdf;filename=MY_CUSTOM_FILENAME.pdf;...),但它被忽略了。

在 Firefox 上,我收到此警告(相关代码在此处):

“getPDFFileNameFromURL:出于性能原因,忽略“数据:”URL。”

并且 pdf 的文件名是默认的document.pdf.

在 Chrome 上,我没有收到任何警告,但文件名坚持默认的download.pdf.

那么,如何自定义文件名呢?那可能吗?

我尝试了这些方法,但没有成功:

  • 检查了 PDFObject,这是一个库,基本上完成了我在这篇文章中所做的工作(在写这篇文章时发现了它!),但它们似乎不允许对文件名进行任何自定义。

  • 我试图在一个 pdf 上加载 pdf <iframe>,然后操作它的内容。但我得到(至少在 Firefox 中)一个跨域错误

  • 似乎 Mozilla 的 PDF 查看器 ( PDF.js ) 也会检查Content-Disposition标题以猜测 pdf 的文件名。是否有可能以某种方式模拟 HTTP 请求(总是在浏览器中本地,因为我使用 base64 字符串)并使用它来加载 pdf 查看器?

我知道解决方案可以直接使用PDF.js,但如果可能的话,我希望避免这种依赖(以及编码,因为实现它并不那么简单)。最后,我只想自定义文件名!

谢谢!


编辑:下面的代码片段在 Chrome 上不起作用(无法将 'data:application/pdf;filename=MY_CUSTOM_FILENAME.pdf;base64,....' 作为插件加载,因为加载插件的框架是沙盒的.),但如果您打开一个计划 .html 文件,它就可以工作。


编辑 2:我找到了一个解决方案,但它只适用于 Firefox。

我们将我们的base64字符串转换为 aBlob 解释here,将其转换Blob为Url 并添加一个filename参数到这个url(使用'#'解释here)。

所以,loadPdf()函数是这样的:

function loadPdf() {
  fetch(pdfData)
    .then(res => res.blob())
    .then(blob => {
      try {
        var blobUrl = URL.createObjectURL(blob)
        // This line makes Chrome crash, we have to remove it there
        // But it works on Firefox
        blobUrl+= '#filename=MY_CUSTOM_FILENAME.pdf'

        var pdf= document.querySelector('.pdf')
        var pobj = document.createElement('object')
        pobj.className= "pdf_object"
        pobj.setAttribute('data', blobUrl)
        pobj.setAttribute('type', 'application/pdf')

        pdf.appendChild(pobj)
      } catch(e) {
        console.error(e)
      }
  })
} 

从 Firefox 的 Pdf 查看器下载时,我们将成功看到 MY_CUSTOM_FILENAME.pdf。

但在 Chrome 上,我们会看到 Blob url 的哈希值。和:

  • 似乎不可能改变那个哈希
  • 即使我使用<iframe>(而不是<object>)来加载我的内联 pdf,Chrome 也会使用<embed>. 所以,没有办法“破解”它。

从这个角度来看还有什么其他提示吗?

4

0 回答 0