How to Set Filename for Base64 Rendered Pdf Using Object Tag

Set the default save as name for a an embed or iframe that uses a Blob


This answer is outdated.

The behavior described below did change since it was posted, and it may still change in the future.

Since this question has been asked elsewhere, with better responses, I invite you to read these instead: Can I set the filename of a PDF object displayed in Chrome?

I didn't find, yet, for chrome's default plugin.

I've got something that works for Firefox though, and which will default to download.pdf in chrome, for some odd reason...

By passing a dataURI in the form of

'data:application/pdf;headers=filename%3D' + FILE_NAME + ';base64,...'

Firefox accepts FILE_NAME as the name of your file, but chrome doesn't...

A plnkr to show a better download.pdf in chrome, which doesn't like nested iframes...

And an snippet which will only work in FF :

const FILE_NAME = 'myCoolFileName.pdf';
const file_header = ';headers=filename%3D';

fetch('').then(r => r.blob())
const f = new FileReader();
f.onload = () => myPdfViewer.src = f.result.replace(';', file_header + encodeURIComponent(FILE_NAME) + ';');
<iframe id="myPdfViewer" width="500" height="500"></iframe>

Can I set the filename of a PDF object displayed in Chrome?

Chrome's extension seems to rely on the resource name set in the URI, i.e the file.ext in protocol://domain/path/file.ext.

So if your original URI contains that filename, the easiest might be to simply make your <object>'s data to the URI you fetched the pdf from directly, instead of going the Blob's way.

Now, there are cases it can't be done, and for these, there is a convoluted way, which might not work in future versions of Chrome, and probably not in other browsers, requiring to set up a Service Worker.

As we first said, Chrome parses the URI in search of a filename, so what we have to do, is to have an URI, with this filename, pointing to our blob:// URI.

To do so, we can use the Cache API, store our File as Request in there using our URL, and then retrieve that File from the Cache in the ServiceWorker.

Or in code,

From the main page

// register our ServiceWorker

async function displayRenamedPDF(file, filename) {
// we use an hard-coded fake path
// to not interfere with legit requests
const reg_path = "/name-forcer/";
const url = reg_path + filename;
// store our File in the Cache
const store = await "name-forcer" );
await store.put( url, new Response( file ) );

const frame = document.createElement( "iframe" );
frame.width = 400
frame.height = 500;
document.body.append( frame );
// makes the request to the File we just cached
frame.src = url;
// not needed anymore
frame.onload = (evt) => store.delete( url );

In the ServiceWorker sw.js

self.addEventListener('fetch', (event) => {
event.respondWith( (async () => {
const store = await"name-forcer");
const req = event.request;
const cached = await store.match( req );
return cached || fetch( req );
})() );

Live example (source)

Edit: This actually doesn't work in Chrome...

While it does set correctly the filename in the dialog, they seem to be unable to retrieve the file when saving it to the disk...

They don't seem to perform a Network request (and thus our SW isn't catching anything), and I don't really know where to look now.

Still this may be a good ground for future work on this.

And an other solution, I didn't took the time to check by myself, would be to run your own pdf viewer.

Mozilla has made its js based plugin pdf.js available, so from there we should be able to set the filename (even though once again I didn't dug there yet).

And as final note, Firefox is able to use the name property of a File Object a blobURI points to.
So even though it's not what OP asked for, in FF all it requires is

const file = new File([blob], filename);
const url = new URL(blob); = url;

how to display base64 encoded pdf?

It should work with Chrome you can use

<iframe src="data:base64...">

<object data="data:base64...">

I've faced the same issue with IE: it's impossible to display a pdf with a base64 string.

I had to generate temporary files on the server to display them with IE he only display existing file by using a path.

You still can use JS library to display your pdf like PDF.js.

Related Topics

Leave a reply