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

使用 Angular 2 使用预签名 URL 上传到 Amazon S3

如何解决使用 Angular 2 使用预签名 URL 上传到 Amazon S3

在我的 Angular/Django Rest 框架中,我想将图片上传到 Amazon S3 存储桶。

我需要使用 Presigned URLs,因为它比直接在客户端上传更快、更安全。

到目前为止,我设法创建并检索了预先签名的 URL,但我正在努力使用它来上传我的图片

这是我在 Django 中用来创建 Presigned Url 的视图:

class GenerateAwsSignature(View):

    def get(self,request,object_name):
        bucket_name = "moviepictures"
        presigned_url = create_presigned_url(bucket_name,object_name)        
        return JsonResponse({"presigned_url": presigned_url})


def create_presigned_url(bucket_name,object_name,fields=None,conditions=None,expiration=3600):

    load_dotenv()
    AWS_KEY_ID = os.environ.get("AWS_ACCESS_KEY_ID")
    AWS_ACCESS_KEY = os.environ.get("AWS_SECRET_ACCESS_KEY")

    s3_client = boto3.client('s3',aws_access_key_id=AWS_KEY_ID,aws_secret_access_key=AWS_ACCESS_KEY)
    response = s3_client.generate_presigned_post(bucket_name,Fields=fields,Conditions=conditions,ExpiresIn=expiration)
    return response

我的组件:

onUpload() {
    const name = this.selectedFile.name
    this.s3Upload.getPresignedUrl(name)
      .subscribe(r => {
        console.log(r)
        this.s3Upload.uploadFile(r,this.selectedFile)
          .subscribe(r => console.log("uploaded :)"))
      })
  }

每当我想将名为“蝙蝠侠”的图片上传到名为“电影图片”的存储桶时,这是我的预签名 URL 的日志:

presigned_url:
fields:
AWSAccessKeyId: "AKIAYHDIXNIEPY2PQJ6V"
key: "batman"
policy: "eyJleHBpcmF0aW9uIjogIjIwMjEtMDctMDhUMTc6MTY6MTdaIiwgImNvbmRpdGlvbnMiOiBbeyJidWNrZXQiOiAibW92aWVwaWN0dXJlcyJ9LCB7ImtleSI6ICJiYXRtYW4ifV19"
signature: "pCjcs4TE1Qyj62v2KveCoMM1tXo="
__proto__: Object
url: "https://moviepictures.s3.amazonaws.com/"

以及上传到我的 Bucket 的服务:

uploadFile(r: any,selectedFile: any) {
    return this.http.put(r['url'],r['fields'],selectedFile)
  }

每当我想上传时,我都会收到此错误

TypeError: 无法读取未定义的属性 'toLowerCase'

那么,使用我必须将图片上传到存储桶中的字段的正确方法是什么?

解决方法

在尝试修复我的代码但没有成功之后,我决定从 s3_client.generate_presigned_post() 切换到 s3_client.generate_presigned_url()。有关它们差异的更多信息,您可以查看此 SO question。 基本上,您不会得到不同的字段,而只会得到一个包含上传所需的一切内容的 url。 只是不要忘记添加 "signature_version" 并且最重要的是用您要上传的 MIME 类型的文件覆盖标题“content-type”。 就我而言,我将 {'content-type': 'imge/jpeg'} 添加到我的标头中,因为默认情况下它会是 'application/xml' 并且我会收到 SignatureDoesNotMatch 错误。

这个方法在 Postman 中 100% 有效,所以我只需要在我的应用中实现它。

 my_config = Config(
        region_name='eu-west-3',signature_version='s3v4',retries = {
            'max_attempts': 10,'mode': 'standard'
        }
    )


def create_presigned_url(bucket_name,object_name,expiration=3600):

    s3_client = boto3.client('s3',aws_access_key_id="#########",aws_secret_access_key="##########",config=my_config)
    try:
        response = s3_client.generate_presigned_url('put_object',Params={'Bucket': bucket_name,'Key': object_name,"ContentType": "image/jpeg" },ExpiresIn=expiration)
    except ClientError as e:
        logging.error(e)
        return None

    return response

url = create_presigned_url("bemytest","batman.jpg")

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