Set the default save as name for a an embed or iframe that uses a Blob
Note:
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('https://dl.dropboxusercontent.com/s/rtktu1zwurgd43q/simplePDF.pdf?dl=0').then(r => r.blob())
.then(blob=>{
const f = new FileReader();
f.onload = () => myPdfViewer.src = f.result.replace(';', file_header + encodeURIComponent(FILE_NAME) + ';');
f.readAsDataURL(blob);
});
<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
navigator.serviceWorker.register('/sw.js')
.then(...
...
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 caches.open( "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 caches.open("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);
object.data = 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
Auto Detect Mobile Browser (Via User-Agent)
What Is the Boundary in Multipart/Form-Data
List of Html5 Elements That Can Be Nested Inside P Element
Google Apps Script to Open a Url
Mystery White Space Underneath Image Tag
How to Get the File Path from HTML Input Form in Firefox 3
Why Are Flex Items Not Wrapping
Css Negation Pseudo-Class :Not() For Parent/Ancestor Elements
Element Will Not Stay Centered, Especially When Re-Sizing Screen
Stretch and Scale CSS Background
How to Make an Image Center (Vertically & Horizontally) Inside a Bigger Div
How to Select the Last Element With a Specific Class, Not Last Child Inside of Parent
Flex Property Not Working in Ie