What to do when the HTML download attribute is ignored
It turns out web browsers will usually ignore the <a download="filename">
HTML attribute on cross-origin requests.
The answer is for the server to set the HTTP Content-Disposition
header in the response:
Content-Disposition: attachment;
This assumes the filename on the server is correct. In my case (for complicated and boring reasons), it is not, so I also need to set a filename in in the Content-Disposition
HTTP header, e.g. Content-Disposition: attachment; filename="example.pdf"
.
In my case, the files are stored on a Google Storage bucket. Their name is not the same as the name the user wants (e.g. the file is called export_yVW4Bg-f63rpZIUiXvWct.pdf
but the user wants export_31Jan2022.pdf
). So when I create the file, I also need to set the Content-Disposition
header accordingly.
This code snippet is part of a Google Cloud Function running on NodeJS, and I’m using the @google-cloud/storage library:
const { Storage } = require("@google-cloud/storage");
// Set the metadata to make the PDF download correctly
const setFileMetadata = async (
bucketName,
fileName,
downloadFileName
) => await storage
.bucket(bucketName)
.file(fileName)
.setMetadata({
contentDisposition: `attachment; filename="${downloadFileName}"`,
contentType: contentType,
});
await setFileMetadata("my-unique-bucket-name", "export_yVW4Bg-f63rpZIUiXvWct.pdf", "export_31Jan2022.pdf");
Google’s engineers have posted a more comprehensive code sample, showing how you can also set other headers (e.g. cache-control
) and metadata on the file.