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 = URL.createObjectURL(file);
object.data = url;
URL.createObjectURL(blob): How do I give a meaningful filename to a dynamically generated .pdf?
One way is to save the file with a filename before it's opened. Unfortunately, this may not automatically open the file.
var fileLink = document.createElement('a');
fileLink.href = fileURL;
fileLink.download = title;
fileLink.click();
Another way is to generate the PDF and filename on your web server, and offer the link remotely, rather than generate the filename locally in the browser. This might offer you more consistent timestamps because they are generated by your server rather than all the clients in different timezones. Then you and your customers will be able to logically refer to identical documents if they have any questions.
Related Topics
Why Aren't Safari or Firefox Able to Process Audio Data from Mediaelementsource
What Cross-Browser Issues Have You Faced
Get All CSS Root Variables in Array Using JavaScript and Change the Values
How to Zoom into a Web Page Like Ie or Firefox Do, Using Programming
Find Unused Images, CSS Rules, Js Script Blocks
Getting Last-Child of a Div in IE8
Automatic Two Columns with CSS or JavaScript
Fastest Selector Method in Jquery and CSS - Id or Not
How to Remove an Important CSS Property
Does the JavaScript Onclick Event Not Work on <Select> <Option>'S
How to Dynamically Adjust CSS Stylesheet Based on Browser Width
Twitter's Typeahead.Js Suggestions Are Not Styled (Have No Border, Transparent Background, etc.)
How to Disable JavaScript/CSS Minification in ASP.NET MVC 4 Beta
How to Get Display:Table-Cell Support in Ie? Any Pure JavaScript or Jquery Workaround
I Need List of All Class Name of Font-Awesome
Image Slider: Maintaining Equal Height for All Images While Keeping Slider Responsive
Google Maps API - Strange Map "Offset" Behaviour
Is It Normal to Have Two Elements with Same Id in Two Div Elements with Other Id