首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >AWS S3 - createPresignedPost不工作.需要一个例子

AWS S3 - createPresignedPost不工作.需要一个例子
EN

Stack Overflow用户
提问于 2022-10-15 17:34:04
回答 1查看 91关注 0票数 0

createPresignedPost()函数不适合我,而且很难确定代码的哪一部分是错误的,因为错误没有显式地声明它。

代码语言:javascript
运行
复制
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { createPresignedPost } from "@aws-sdk/s3-presigned-post";
import { env } from "@/env/server.mjs";

// Instantiating the client
const accessKeyId = env.AWS_S3_ACCESS_KEY;
const secretAccessKey = env.AWS_S3_SECRET_KEY;
const client = new S3Client({
    region: "us-east-1",
    credentials: { accessKeyId, secretAccessKey },
});

// Defining variables
const Bucket = "my-unique-awsbucket";
const Key = "user/" + 123 + "/avatar";
const Fields = {
    acl: "public-read",
    key: Key,
};

// Getting the presignedPost info
const { url, fields } = await createPresignedPost(client, {
    Bucket,
    Key,
    Fields,
    Expires: 600, // Expires in 10 minutes
    });

这些是我得到的回报

代码语言:javascript
运行
复制
{
  url: "https://s3.us-east-1.amazonaws.com/my-unique-awsbucket",
  fields: {
  acl: 'public-read',
  key: 'user/123/avatar',
  bucket: 'my-unique-awsbucket',
  'X-Amz-Algorithm': 'AWS4-HMAC-SHA256',
  'X-Amz-Credential': '<IAM_user_id>/20221015/us-east-1/s3/aws4_request',
  'X-Amz-Date': '20221015T170146Z',
  Policy: 'hidden',
  'X-Amz-Signature': 'hidden'
  }
}

我要发布到s3的代码

代码语言:javascript
运行
复制
import FormData from "form-data";

const form = new FormData();
Object.entries(fields).forEach(([field, value]) => {
    form.append(field, value);
});

const imagepath = path.join(process.cwd(), "mountains.jpg");
const img = fs.readFileSync(imagepath); // <- Also tried a readstream but no difference
form.append("file", img);

// As per docs
form.submit(url, (err, res) => {
    if (err) {
        console.log("form.submit: err", err);
    }
    console.log("Done.")
});

AWS博士 \

根据我尝试的内容,我得到的错误是不同的。

  1. 如果我用Postman来尝试,我会看到XML表示Access Denied
  2. 如果我用axios来尝试,我会.MissingContentLength - You must provide the Content-Length HTTP header...当我添加那个头和文件的大小时,它是AccessControlListNotSupported - The bucket does not allow ACLs。我在Fields下删除acl密钥,然后使用MalformedPOSTRequest - The body of your POST request is not well-formed multipart/form-data错误。
  3. 当我和form.submit试一试.它甚至没有显示错误,但在桶中没有显示任何图像。
  4. 更奇怪的是,当我放置一个随机的、不正确的secretAccessKey时,它仍然会释放出一个urlfield参数,所以如果IAM是错误的,或者我的发布方法,或者标题,或者文件类型,就很难缩小范围.

AWS:我的IAM用户只允许用户使用PutObject访问级别。我觉得这有足够的权限?我没有看到PostObject权限,所以我认为Put就足够了,或者我可能授予了错误的权限,因为我是POSTing而不是PUTing?

我的水桶政策

代码语言:javascript
运行
复制
{
    "Version": "2012-10-17",
    "Id": "Policy123",
    "Statement": [
        {
            "Sid": "hidden",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-unique-awsbucket/*"
        }
    ]
}

我的CORS政策

代码语言:javascript
运行
复制
[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "PUT",
            "POST",
            "HEAD",
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]

有没有人有一个明确的例子,如何上传到这个预先签名的URL?

EN

回答 1

Stack Overflow用户

发布于 2022-10-15 19:15:02

最后这件事对我有用。值得注意的是:

  • 不包括任何acl策略
  • 还是不能让公理起作用。使用formData提交。
代码语言:javascript
运行
复制
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { createPresignedPost } from "@aws-sdk/s3-presigned-post";
import fs from "fs";
import path from "path";
import FormData from "form-data";

const getPresignedPostUrl = async ({ id }) => {
    // Instantiating the client
    const client = new S3Client({
        region: "us-east-1",
        credentials: {
            accessKeyId: <enter-access-key-id>,
            secretAccessKey: <enter-secret-access-key>,
        },
    });

    const filename = "mountains.jpg";

    // Creating the presignedPostUrl 
    const { url, fields } = await createPresignedPost(client, {
        Bucket: "my-unqiue-awsbucket",
        Key: `user/${id}/${filename}`,
        Conditions: [
            { bucket: "my-unqiue-awsbucket" },
            ["starts-with", "$key", `user/${id}`],
            ["content-length-range", 0, 1000000],
        ],
        Fields: {
            key: `user/${id}/${filename}`,
        },
        Expires: 600, // Expires in 10 minutes
    });

    // Filling in the form data with the `form-data` package 
    const formData = new FormData();
    Object.entries(fields).map(([key, value]) => {
        formData.append(key, value);
    });
    const imgpath = path.join(process.cwd(), filename);
    const file = fs.readFileSync(imgpath, "utf-8");
    formData.append("file", file);

    // POSTing the form to aws
    formData.submit(url, (err, res) => {
        if (err) {
            console.log("form.submit: err", err.response.data);
        }
        console.log("Done.", res.response);
    });
};

修改:在使用浏览器时尝试了这个名为ky-universalky的库,哇,它只是起作用了,而且代码比axios少得多。下面是与AWS S3相关的S3。

Amendment2:got包也运行得很好。只需将ky替换为got,语法相同--非常简单,而且代码少得多。显然,它是由相同的人制作的,ky用于浏览器,got用于nodejs/服务器端请求。

代码语言:javascript
运行
复制
import ky from 'ky-universal';

const response = await ky.post(url, {
    body: formData
});
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74081648

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档