Reputation: 5678
I have an S3 bucket having PDF files as objects and all of them are private. I create an S3 Presigned URL programmatically to get the object. It works fine. Now, I want it to be previewable as a PDF. Every object already has a Content-Type
header set to application/pdf
. Now, if I set the response-content-disposition
header as a query parameter, it gets set but doesn't override the already existing Content-disposition
header, instead, it creates a new one. If I set the Content-Disposition
header in the metadata of the S3 object instead of adding it in the S3 Presigned URL as a query parameter, it still shows 2 headers. Is this some kind of bug on the AWS S3 side?
Below is the screenshot of the Response Header for reference.
Any help will be much appreciated. Thanks.
Upvotes: 18
Views: 23176
Reputation: 5678
I have solved this issue using the latest API available for this thing from AWS SDK for NodeJS using the following code:
const aws = require('aws-sdk');
const AWS_SIGNATURE_VERSION = 'v4';
const s3 = new aws.S3({
accessKeyId: <aws-access-key>,
secretAccessKey: <aws-secret-access-key>,
region: <aws-region>,
signatureVersion: AWS_SIGNATURE_VERSION
});
/**
* Return a signed document URL given a Document instance
* @param {object} document Document
* @return {string} Pre-signed URL to document in S3 bucket
*/
const getS3SignedDocumentURL = (docName) => {
const url = s3.getSignedUrl('getObject', {
Bucket: <aws-s3-bucket-name>,
Key: <aws-s3-object-key>,
Expires: <url-expiry-time-in-seconds>,
ResponseContentDisposition: `attachment; filename="${docName}"`
});
return url;
};
/**
* Return a signed document URL previewable given a Document instance
* @param {object} document Document
* @return {string} Pre-signed URL to previewable document in S3 bucket
*/
const getS3SignedDocumentURLPreviewable = (docName) => {
const url = s3.getSignedUrl('getObject', {
Bucket: <aws-s3-bucket-name>,
Key: <aws-s3-object-key>,
Expires: <url-expiry-time-in-seconds>,
ResponseContentDisposition: `inline; filename="${docName}"`
});
return url;
};
module.exports = {
getS3SignedDocumentURL,
getS3SignedDocumentURLPreviewable
};
Note: Don't forget to replace the placeholders (<...>) with actual values to make it work.
Upvotes: 32
Reputation: 1736
It's strange how often we overlook things like filenames where comma (,)
could be common if it is user generated name.
While setting response-content-disposition
make sure to strip special character or properly escape the filename attribute
Refer https://stackoverflow.com/a/6745788/8813684 for more details
Upvotes: 3