![](/img/trans.png)
[英]How to make an AWS S3 file public accessible using AW S3 SDK's createPresignedPost method?
[英]How to upload an image file directly from client to AWS S3 using node, createPresignedPost, & fetch
我正在使用
在我的服務器上生成 AWS S3 預簽名帖子 object。 然后我嘗試使用預先簽名的帖子 url & 字段使用 fetch 將文件直接從客戶端上傳到 S3 存儲桶,但我收到了s3.createPresignedPost()
403 Forbidden
。
我嘗試手動將表單字段添加到我的 FormData object 以直接匹配此示例: https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.html但繼續收到 403 錯誤.
服務器端 function 用於生成帖子 object
const AWS = require("aws-sdk/global"); const S3 = require("aws-sdk/clients/s3"); const uuidv4 = require("uuid/v4"); AWS.config.update({ accessKeyId: process.env.S3_KEY_ID, secretAccessKey: process.env.S3_SECRET_KEY, region: "us-east-1" }); const s3 = new S3(); const getPresignedPostData = (bucket, directory) => { const key = `${directory}/${uuidv4()}`; const postData = s3.createPresignedPost({ Bucket: bucket, Fields: { Key: key, success_action_status: "201" }, Conditions: [{ acl: "public-read" }], ContentType: "image/*", Expires: 300 }); return postData; };
返回看起來像這樣的東西:
{ fields: { Key: "5cd880a7f8b0480b11b9940c/86d5552b-b713-4023-9363-a9b36130a03f" Policy: {Base64-encoded policy string} X-Amz-Algorithm: "AWS-HMAC-SHA256" X-Amz-Credential: "AKIAI4ELUSI2XMHFKZOQ/20190524/us-east-1/s3/aws4_request" X-Amz-Date: "20190524T200217Z" X-Amz-Signature: "2931634e9afd76d0a50908538798b9c103e6adf067ba4e60b5b54f90cda49ce3" bucket: "picture-perfect-photos" success_action_status: "201" }, url: "https://s3.amazonaws.com/picture-perfect-photos" }
我的客戶端 function 看起來像:
const uploadToS3 = async ({ fields, url }, file) => { const formData = new FormData(); Object.keys(fields).forEach(key => formData.append(key, fields[key])); formData.append("file", file); try { const config = { method: "POST", body: formData }; const response = await fetch(url, config); if (!response.ok) { throw new Error(response.statusText); } const data = await response.json(); return data; } catch (err) { console.log(err.message); } };
我的 S3 存儲桶 CORS 配置如下:
<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <AllowedMethod>POST</AllowedMethod> <AllowedMethod>PUT</AllowedMethod> <AllowedMethod>DELETE</AllowedMethod> <AllowedHeader>*</AllowedHeader> </CORSRule> </CORSConfiguration>
我希望獲得 XML 文檔,該文檔在設置 success_action_status success_action_status: "201"
時發送,但我不斷收到403 Forbidden
我剛剛經歷了同樣的問題。
將<AllowedMethod>PUT</AllowedMethod>
和<AllowedHeader>Content-*</AllowedHeader>
到 S3 控制台中 S3 存儲桶的 CORS 規則。
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedHeader>Content-*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
向您的服務器發出發布請求以獲取預簽名的 S3 URL。 發布請求應在正文中包含文件名和 MIME 類型:
快速路線:
app.post("/s3-signed-url",async (req, res, next)=>{
const s3 = new AWS.S3();
const url = await s3.getSignedUrlPromise('putObject', {
Bucket: "BUCKET_NAME",
Key: req.body.name,
ContentType: req.body.type,
Expires: 60,
ACL: 'public-read',
});
res.json({signedUrl: url})
});
選擇要上傳的文件時異步函數中的客戶端代碼:
async function onFileDrop(file){
const {name, type} = file; // I use react-dropzone to obtain the file.
const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({name,type})
}
const rawResponse = await fetch("/s3-signed-url", options)
const {signedUrl} = await rawResponse.json();
// After you obtain the signedUrl, you upload the file directly as the body.
const uploadOptions = { method: 'Put', body: file,}
const res = await fetch(signedUrl, uploadOptions);
if(res.ok) {
return res.json()
}
}
我的致命錯誤是在上傳帶有簽名 URL 的文件時,我在uploadOptions
添加了多余的標頭。 我遇到了其他線程,聲稱我必須明確添加“Content-Type”標頭:
`const wrongUploadOptions = { method: 'Put', body: file, headers:{"Content-Type": file.type, "x-amz-acl": public-read}}`
但這在我的情況下完全沒有必要,這就是我收到 403 錯誤的原因。
這個線程上唯一的其他答案是談論完全不同的 S3 API 調用。
有 2 個相似但不同的 API:
我自己需要createPresignedPost
並且之前使用getSignedUrl
因為我想限制可以上傳的文件大小遠小於 AWS S3 支持的文件大小。 在我的例子中,我讓用戶上傳圖片。 大小可達 10MB。 從客戶端上傳時,我需要限制文件上傳大小的方法。 如果你用谷歌搜索這種情況,人們建議刪除已經上傳的大文件,但我不喜歡讓上傳開始。
因此,在使用實際的createPresignedPost
API 調用時,您不僅會返回url
,還會返回fields
。
字段是 object 鍵值對。
在客戶端,您需要:
將 POST 請求發送到 url( getSignedUrl
需要 PUT)並且您獲得的所有字段都必須作為表單字段提供。 只有額外的表單字段稱為file
,這是您放置上傳文件的地方。
這是 PostMan 屏幕截圖示例,其中包含所有表格:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.