Billybobbonnet
Billybobbonnet

Reputation: 3226

Why is my pdf uploaded using a presigned AWS S3 url does not have the correct content type?

I use AWS S3 with presigned urls both for uploading (putObject) and downloading (getObject).

I noticed that the generated urls to load pdfs are downloaded instead of being displayed in the _blank target. I tracked it down to the fact that my s3 objects have a metadata field ContentType set to application/x-www-form-urlencoded instead of application/pdf as I requested. It works when I manually change the content type metadata on S3.

The code used to generate the presigned putObject url is this:

console.log("presigning with ", fileInput);
/* Will print something like:
presigning with  [Object: null prototype] {
  name: 'myFile.pdf',
  mimetype: 'application/pdf',
  size: 321528
}
*/
const { name, size, mimetype } = fileInput
const signedUrlExpireSeconds = 60 * 60
let data = {}
const key = "articles/" + Date.now().toString() + ".pdf"
let params = {
       Bucket: 'mybucket',
       Key: key,
       Expires: signedUrlExpireSeconds,
       ContentType: mimetype
};
data.url = await uploadToS3(params)// what I will use to upload from the client browser


export const uploadToS3 = (params) => {
    AWS.config.update({
        accessKeyId: process.env.S3ACCESSKEYID,
        secretAccessKey: process.env.S3SECRETACCESSKEY,
        region: process.env.S3REGION
    });
    var s3 = new AWS.S3();
    return s3.getSignedUrlPromise('putObject', params);
}

The generated url contains indeed the content type option like follows (truncated url):

https://mybucket.s3.eu-west-3.amazonaws.com/articles/1582299553999.pdf?Content-Type=application%2Fpdf&X-Amz-Algorithm......

However, when I try to display my pdf in a _blank tab, the browser downloads it because of the faulty application/x-www-form-urlencoded content type set during the S3 upload.

I assume the getObject presigned url is ok since it works when I manually update on S3 the content type of the file.

Am I missing something with the upload?


UPDATE

I wondered if maybe it was related to the axios put request made on the basis of the presigned url. Based on this issue comments, I managed to get the proper content type.

However, The pdf does not load because the favicon is not available... There is 2 network call, one for the pdf that ok with 304, and one for a favicon that gets a 400 bad request on firefox, and a 403 forbidden on chromium. As a consequence (it seems), the pdf file is seen as invalid.

I made the favico file the only public one, but the PDF is still seen as invalid. However, it displays correctly when downloaded.

Upvotes: 4

Views: 3588

Answers (1)

Renan Cidale
Renan Cidale

Reputation: 902

For everyone's future reference, when sending a presigned URL request, you need to provide the Content-Type in the request, in the axios, or whatever is your http client. Otherwise it will be given this application/x-www-form-urlencoded. That's why when you retrieve with .getObject , you see the Content-Type set to application/x-www-form-urlencoded.

Upvotes: 3

Related Questions