I have this code that creates a signed URL to download a specific file in my bucket:
exports.download = functions.https.onRequest((req, res) => {
const userID = req.query.userID;
const downloadID = req.query.downloadID;
const fileName = req.query.fileName;
admin
.storage()
.bucket()
.file(`userUploads/${userID}/${downloadID}/${fileName}`)
.getSignedUrl({
version: "v4",
action: "read",
expires: Date.now() + 15 * 60 * 1000, // 15 minutes
})
.then((signedURLArray) => {
const url = signedURLArray[0];
// return res.download(url);
return res.redirect(url);
})
.catch((err) => {
return res.send(err);
});
});
I've tried:
res.setHeader(
`"content-disposition", "attachment; filename=${fileName}"`
);
with res.redirect but it just gives me a HTTP_TOKEN_ERROR . If I use res.redirect() without setting any extra headers, it will just view the file on the browser, not download it - I only want the user to be able to download the file.
Obviously, res.download does not work as the file in question is not on the server, it is served on some other server where my bucket files are located (most likely some storage.googleapis.com domain)
UPDATE:
As you can see by the response request:
It's sending the right data back to the browser
As you redirect to google's server, it becomes responsible for the headers of the response, and specifically for the Content-disposition one. Metadata of the files stored in google storage can be set up on or after the file is uploaded.
Your header should look like:
Content-Disposition: attachment; filename="file.ext..."
Please check these docs to see possible options on how to set the metadata for the files manually via gsutil:
In order to generate signed URL with custom header (e.g. Content-Disposition) with the Google storage admin API it should be added via a config parameter responseDisposition with desired value
Usage example:
...
admin
.storage()
.bucket()
.file(`userUploads/${userID}/${downloadID}/${fileName}`)
.getSignedUrl({
responseDisposition: "attachment",
version: "v4",
action: "read",
expires: Date.now() + 15 * 60 * 1000, // 15 minutes
})
...
See MDN reference for possible header values here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
See documentation for nodejs api library for google storage here and link to the lines where file attachment properties, promptSaveAs and responseDisposition are explained here.