为什么我使用预签名 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
.
我使用带有预签名 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
.