In my Vue app I receive a PDF as a blob, and want to display it using the browser's PDF viewer.
I convert it to a file, and generate an object url:
const blobFile = new File([blob], `my-file-name.pdf`, { type: 'application/pdf' }) this.invoiceUrl = window.URL.createObjectURL(blobFile)
Then I display it by setting that URL as the data
attribute of an object element.
<object :data="invoiceUrl" type="application/pdf" width="100%" style="height: 100vh;"> </object>
The browser then displays the PDF using the PDF viewer. However, in Chrome, the file name that I provide (here, my-file-name.pdf) is not used: I see a hash in the title bar of the PDF viewer, and when I download the file using either 'right click -> Save as...' or the viewer's controls, it saves the file with the blob's hash (cda675a6-10af-42f3-aa68-8795aa8c377d
or similar).
The viewer and file name work as I'd hoped in Firefox; it's only Chrome in which the file name is not used.
Is there any way, using native Javascript (including ES6, but no 3rd party dependencies other than Vue), to set the filename for a blob / object element in Chrome?
[edit] If it helps, the response has the following relevant headers:
Content-Type: application/pdf; charset=utf-8 Transfer-Encoding: chunked Content-Disposition: attachment; filename*=utf-8''Invoice%2016246.pdf; Content-Description: File Transfer Content-Encoding: gzip
First, select File->Action Wizard->Insert Filename into Title Field. A window describing the Action will appear. Click Next. Here, select the documents the Action will be run on by selecting the Add Files button.
Type or paste chrome://settings/content into address bar. A pop-up labeled "Content Settings..." will open. Scroll down to the bottom to "PDF Documents" Select or deselect the check box labelled "Open PDF files in the default PDF viewer application"
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)
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;
In Chrome, the filename is derived from the URL, so as long as you are using a blob URL, the short answer is "No, you cannot set the filename of a PDF object displayed in Chrome." You have no control over the UUID assigned to the blob URL and no way to override that as the name of the page using the object
element. It is possible that inside the PDF a title is specified, and that will appear in the PDF viewer as the document name, but you still get the hash name when downloading.
This appears to be a security precaution, but I cannot say for sure.
Of course, if you have control over the URL, you can easily set the PDF filename by changing the URL.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With