I'm embedding PDFs from a base64 string like this:
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>
This works both on Firefox and Chrome.
My problem is I cannot customize the filename for the pdf download actions. Notice that I'm using the filename
parameter ('data:application/pdf;filename=MY_CUSTOM_FILENAME.pdf;...
), but it's ignored.
On Firefox, I get this warning (related code is here):
"getPDFFileNameFromURL: ignoring "data:" URL for performance reasons."
And the pdf's filename is the default document.pdf
.
On Chrome, I get no warning, but filename sticks to the default download.pdf
.
So, how can I customize the filename? Is that possible?
I tried these ways, unsuccessfully:
Checked PDFObject, which is a library doing basically what I'm doing in this post (discovered it while writing this!), but they seem to not allow any customization on the filename.
I tried to load pdf on an
<iframe>
, and then manipulating its content. But I get (at least in Firefox) a Cross Origin errorIt seems that Mozilla's PDF viewer (PDF.js) also checks the
Content-Disposition
header for guessing out the pdf's filename. Could be possible to somehow simulate an HTTP request (always locally in the browser, as I work with base64 strings) and use it to load the pdf viewer?
I know the solution can be to directly use PDF.js, but if possible I would love to avoid this dependency (and also the coding, cause it's not so straightforward to implement it). At the end, I just want to customize filename!
Thanks!
EDIT: The code snippet below does not work on Chrome (Failed to load 'data:application/pdf;filename=MY_CUSTOM_FILENAME.pdf;base64,....' as a plugin, because the frame into which the plugin is loading is sandboxed.), but it works if you open a plan .html file.
EDIT 2: I found a solution but it just works on Firefox.
We will convert our base64
string to a Blob
as explained here, convert this Blob
to Url and add a filename
parameter to this url (using '#' as explained here).
So, the loadPdf()
function is this:
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)
}
})
}
When downloading from Firefox's Pdf viewer, we'll successfully see MY_CUSTOM_FILENAME.pdf.
But on Chrome we will see the Blob url's hash. And:
- it seems impossible to change that hash
- even if I use an
<iframe>
(instead of an<object>
) to load my inline pdf, Chrome will make use of an<embed>
. So, there's no way to "hack" it.
Any other tip from this perspective?