0

我和 Vultr 合作了很长时间,当我想存储一些媒体文件时,我想到了 AWS 的 S3,而 Vultr 提供了 S3 兼容的服务(对象存储)。我可以使用 s3cmd CLI 来玩服务,他们指向使用 boto3 与 S3 服务交互。我想让我的对象有签名的 URL,但我相信 boto3amazonaws.com在代码中的某处将主机名作为常量,并且不能从配置中更改,如下所示:

import logging
from django.conf import settings
import boto3
from botocore.exceptions import ClientError
from premarket.models import PreMarket
from .models import SupervisorLogs


class Supervisor():

    def __init__(self) -> None:
        self.bucket_name = settings.BUCKET_NAME
        self.link_expiration = settings.ONE_WEEK
        self.queryset = PreMarket.objects.all()
        # Generate a presigned URL for the S3 object
        self.s3_configs_object = settings.AWS_S3_CREDS
        self.s3_client = boto3.client('s3', **self.s3_configs_object)

    def sign_objects(self):
        for obj in self.queryset:
            try:
                presigned_url = self.create_presigned_url(obj.video_url)
                obj.presigned_url = presigned_url
                obj.save()
            except Exception as e:
                self.supervisor_logs(level="ERROR", message=e, description=e)
                logging.error(e)
        self.supervisor_logs(level="COMPLETE",
                            message="Object URL signing has completed",
                            description="Object URL signing has completed")

    def create_presigned_url(self, object_name):
        """Generate a presigned URL to share an S3 object

        :param object_name: string
        :return: Presigned URL as string. If error, returns None.
        """

        try:
            response = self.s3_client.generate_presigned_url('get_object',
                                                            Params={
                                                                'Bucket': self.bucket_name,
                                                                'Key': object_name},
                                                            ExpiresIn=self.link_expiration)
        except ClientError as e:
            logging.error(e)
            self.supervisor_logs(level="ERROR", message=e, description=e)
            return None

        # The response contains the presigned URL
        return response

    def supervisor_logs(self, message: str = None, level: str = None, description: str = None) -> None:
        SupervisorLogs.objects.create(
            message=message, level=level, description=description)

AWS S3 凭证:

AWS_S3_CREDS = {
    'aws_access_key_id': AWS_ACCESS_KEY_ID,
    'aws_secret_access_key': AWS_SECRET_ACCESS_KEY,
    'region_name': 'ewr',
    'endpoint_url': AWS_BUCKET_HOSTNAME
}

但是 Vultr 提供了不同的主机名,如下所示:

ewr1.vultrobjects.com

对象示例:

https://ewr1.vultrobjects.com/my-s3-bucket/basics/video.mp4

尝试使用我上面编写的代码对其进行签名会产生以下结果(不起作用):

https://ewr1.vultrobjects.com/my-s3-bucket/https%3A//ewr1.vultrobjects.com/my-s3-bucket/basics/video.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AccessKeyHere%2F20210706%2Fewr%2Fs3%2Faws4_request&X-Amz-Date=20210706T133319Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=bb7da3183691052ea5b25218ab1fb876fec7053a2b045957fec12cd131393a19

乍一看有几个问题:URL 是无效的,就好像它正在被连接一样,即使我出于测试目的手动删除它,它仍然无法正常工作。

Vultr 没有提供任何有关此的文件,因为他们的支持已通知我。在这一点上,我想知道我如何才能访问这些对象(没有预签名的 URL),只使用仍然无法工作的访问密钥。

我不知道我错过了什么,我希望有人对此有一些经验,因为我在过去几天找不到任何东西?

谢谢您的帮助。

4

1 回答 1

0

上面的代码让你使用 URL:

 presigned_url = self.create_presigned_url(obj.video_url)

您是否尝试过使用 s3 位置来生成 URL?从外观上看,obj.video_url 是 https://ewr1...... 而 s3 URL 是 s3:// 并且可能会被您正在使用的库更好地使用。

此外,在为每个 URL 执行整个循环之前,我会尝试一些手动操作,例如:

presigned_url = self.create_presigned_url('s3://ewr1.vultrobjects.com/my-s3-bucket/basics/video.mp4')

看看这是否让你感到高兴。

于 2021-07-12T15:51:45.103 回答