微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

带有 React 的 AWS S3 预签名 url 上传空文件

如何解决带有 React 的 AWS S3 预签名 url 上传空文件

我正在使用 React、API 网关和 Lambda (Python) 来获取预签名的 url 以将文件上传到 s3 存储桶。但是上传到 s3 存储桶的文件始终为空(0 字节)。出于某种原因,当我在 React 应用程序中上传 CSV 文件时。 s3 中上传文件变成了 .XLS 文件,但仍命名为原始 csv。

这是我的代码

<div>
    <input type="file" name="fileOne" onChange={fileUploadOne} />
</div>

...

const fileUploadOne = (event) => {
    const { files } = event.target;
    getPresignedUrl(files[0]).then((response) => {
      putToS3(files[0],response);
    });
  };

...

export async function getPresignedUrl(fileObject) {
  const requestOptions = {
    method: "GET",headers: {
      "Content-Type": "application/json",},};
  const response = await fetch(
    "https://<api_gateway_url>.amazonaws.com/<api_name>?filename=" +
      fileObject.name +
      "&filetype=" +
      fileObject.type,requestOptions
  );
  return await response.json();
}

export async function putToS3(fileObject,presignedUrl) {
  const requestOptions = {
    method: "PUT",headers: {
      "Content-Type": fileObject.type,data: fileObject,};
  const response = await fetch(presignedUrl,requestOptions);
  return await response;
}

我的 Lambda 代码(通过 getPresignedUrl 函数访问):

import json
import boto3
from botocore.exceptions import ClientError

def lambda_handler(event,context):
    params = event["querystringparameters"]
    key = params.get('filename')
    filetype = params.get('filetype')
    
    s3_client = boto3.client('s3')
    client_action = 'put_object'
    bucket_name = '<bucket_name>'
    resp = generate_presigned_url(
        s3_client,client_action,{'Bucket': bucket_name,'Key': key,'ContentType':filetype},1000)
    return {
        'statusCode': 200,'headers': {
            "Access-Control-Allow-Origin" : "*",# required for CORS support to work
        },'body': json.dumps(resp)
    }

def generate_presigned_url(s3_client,client_method,method_parameters,expires_in):
    """
    Generate a presigned Amazon S3 URL that can be used to perform an action.

    :param s3_client: A Boto3 Amazon S3 client.
    :param client_method: The name of the client method that the URL performs.
    :param method_parameters: The parameters of the specified client method.
    :param expires_in: The number of seconds the presigned URL is valid for.
    :return: The presigned URL.
    """
    try:
        url = s3_client.generate_presigned_url(
            ClientMethod=client_method,Params=method_parameters,ExpiresIn=expires_in
        )
        print("Got presigned URL: %s",url)
    except ClientError:
        print(
            "Couldn't get a presigned URL for client method '%s'.",client_method)
        raise
    return url

解决方法

我发现了我的错误。我的 HTTP PUT 请求应该在 body 中包含 fileObject 而不是数据。

export async function putToS3(fileObject,presignedUrl) {
  const requestOptions = {
    method: "PUT",headers: {
      "Content-Type": fileObject.type,},body: fileObject,};
  const response = await fetch(presignedUrl,requestOptions);
  return await response;
}

这真的很简单,而且是一个愚蠢的错误。我花了几个小时才弄明白。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?