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
CodePudding user response:
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:
- https://cloud.google.com/storage/docs/gsutil/addlhelp/WorkingWithObjectMetadata
- https://cloud.google.com/storage/docs/metadata#content-disposition
# UPDATE
In order to generate signed URL with custom header (e.g. Content-Disposition) it should be added a config parameter responseDisposition with desired value, like for example:
attachment; filename="file.ext..."
Usage example:
...
admin
.storage()
.bucket()
.file(`userUploads/${userID}/${downloadID}/${fileName}`)
.getSignedUrl({
responseDisposition: 'attachment; filename="file.ext"',
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.

