为什么我使用预签名 AWS S3 url 上传的 pdf 没有正确的内容类型?

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

我使用带有预签名 url 的 AWS S3 进行上传 (putObject) 和下载 (getObject)。

我注意到生成的用于加载 pdf 的 url 被下载,而不是显示在 _blank 目标中。我追踪到我的 s3 对象有一个元数据字段 ContentType 设置为 application/x-www-form-urlencoded 而不是我请求的 application/pdf 的事实。它在我手动更改 S3 上的内容类型元数据时有效。

用于生成预签名 putObject url 的代码是这样的:

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);
}

生成的 url 确实包含如下内容类型选项(截断 url):

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

但是,当我尝试在 _blank 选项卡中显示我的 pdf 时,浏览器会下载它,因为在 S3 上传期间设置了错误的 application/x-www-form-urlencoded 内容类型。

我假设 getObject 预签名 url 没问题,因为当我在 S3 上手动更新文件的内容类型时它可以工作。

我上传的东西是不是遗漏了什么?


更新

我想知道这是否与基于预签名 url 的 axios put 请求有关。基于 on this issue comments,我设法获得了正确的内容类型。

但是,pdf 没有加载,因为 favicon 不可用...有 2 个网络调用,一个用于 pdf,可以使用 304,另一个用于 favicon,在 firefox 上收到 400 错误请求,和 403 禁止使用铬。结果(看起来)pdf 文件被视为无效。

我将 favico 文件设为唯一 public,但 PDF 仍被视为无效。但是,下载后它会正确显示。

为了大家以后的参考,当发送一个预签名的URL请求时,你需要在请求中提供Content-Type,在axios中,或者你的http客户端。否则会给出这个application/x-www-form-urlencoded。 这就是为什么当您使用 .getObject 检索时,您会看到 Content-Type 设置为 application/x-www-form-urlencoded.