使用 django-storages 时如何添加 user-defined S3 元数据
How do you add user-defined S3 metadata in when using django-storages
我在 django-storages 1.12.3 中使用 django 3.1.0。
我正在使用 S3 后端来存储媒体文件 (Minio)。
我正在尝试 post 文件到 S3,并将额外的用户元数据包含到 S3 object。这个额外的元数据来自用于将文件上传到 django 的 POST 请求。使用 S3,可以添加自定义元数据,方法是将额外的 key-value 对添加到 HTTP header 中,以便在上传文件时发送到 S3 服务器的 POST 请求,其中自定义键是前缀为 'X-Amz-Meta-'.
我在 Django 模型中使用 FileField,文件是使用 REST API 端点上传的。
据我了解,当django收到文件时,它会暂时存储它,然后在模型实例上保存FielField时,文件被posted到S3服务器。我想修改流程,以便从请求中获取自定义元数据并将其包含在 post 到 S3 服务器中。
知道如何从初始请求中获取数据,并将其传递给发送到 S3 的 POST 请求的 header 吗?
更新
在尝试了 Helge Schneider 的回答中的选项 1 后,我做了一些修改并让它工作。
我使用的是django rest framework,所以我修改了serializer.save()方法。
from .models import MyModel
from rest_framework import serializers
class MyModelSerialzer(serializers.ModelSerializer):
class Meta:
model = SessionFile
fields = ['file', 'my_other_field']
def save(self):
file = self.validated_data['file']
my_other_field = self.validated_data['my_other_field']
mymodel = MyModel(file=file, my_other_field=my_other_field)
options_dict = {"Metadata": {"metadata1": "ImageName",
"metadata2": "ImagePROPERTIES",
"metadata3": "ImageCREATIONDATE"}
}
mymodel.file.storage.object_parameters.update(options_dict)
mymodel.save()
有两种可能的选择:
1.在调用保存方法之前更新存储的参数class
一个选项是在调用保存方法和更新 object_parameters 属性之前从模型的文件字段更新存储 class。
views.py
import MyModel
def my_view(request):
mymodel = MyModel()
options_dict = {"Metadata": {"metadata1": "ImageName",
"metadata2": "ImagePROPERTIES",
"metadata3": "ImageCREATIONDATE"}
}
mymodel.filefield.storage.object_parameters.update(options_dict)
mymodel.filefield.save()
2。使用 boto3
手动上传文件
另一种选择是使用 boto3
客户端手动上传文件(Documentation with the upload_fileobj 方法。
然后您可以使用以下摘自 this answer 的代码设置对象元数据:
import boto3
s3 = boto3.resource('s3')
options_dict = {"Metadata": {"metadata1": "ImageName",
"metadata2": "ImagePROPERTIES",
"metadata3": "ImageCREATIONDATE"}
s3.upload_fileobj(file, bucketname, key, ExtraArgs=options_dict)
之后,您必须将 FileField 的 name
属性 设置为 S3 Bucket 中的键,如 this answer.
中所述
object.filefield.name = 'file/key/in/bucket'
我在 django-storages 1.12.3 中使用 django 3.1.0。 我正在使用 S3 后端来存储媒体文件 (Minio)。 我正在尝试 post 文件到 S3,并将额外的用户元数据包含到 S3 object。这个额外的元数据来自用于将文件上传到 django 的 POST 请求。使用 S3,可以添加自定义元数据,方法是将额外的 key-value 对添加到 HTTP header 中,以便在上传文件时发送到 S3 服务器的 POST 请求,其中自定义键是前缀为 'X-Amz-Meta-'.
我在 Django 模型中使用 FileField,文件是使用 REST API 端点上传的。 据我了解,当django收到文件时,它会暂时存储它,然后在模型实例上保存FielField时,文件被posted到S3服务器。我想修改流程,以便从请求中获取自定义元数据并将其包含在 post 到 S3 服务器中。
知道如何从初始请求中获取数据,并将其传递给发送到 S3 的 POST 请求的 header 吗?
更新
在尝试了 Helge Schneider 的回答中的选项 1 后,我做了一些修改并让它工作。
我使用的是django rest framework,所以我修改了serializer.save()方法。
from .models import MyModel
from rest_framework import serializers
class MyModelSerialzer(serializers.ModelSerializer):
class Meta:
model = SessionFile
fields = ['file', 'my_other_field']
def save(self):
file = self.validated_data['file']
my_other_field = self.validated_data['my_other_field']
mymodel = MyModel(file=file, my_other_field=my_other_field)
options_dict = {"Metadata": {"metadata1": "ImageName",
"metadata2": "ImagePROPERTIES",
"metadata3": "ImageCREATIONDATE"}
}
mymodel.file.storage.object_parameters.update(options_dict)
mymodel.save()
有两种可能的选择:
1.在调用保存方法之前更新存储的参数class
一个选项是在调用保存方法和更新 object_parameters 属性之前从模型的文件字段更新存储 class。
views.py
import MyModel
def my_view(request):
mymodel = MyModel()
options_dict = {"Metadata": {"metadata1": "ImageName",
"metadata2": "ImagePROPERTIES",
"metadata3": "ImageCREATIONDATE"}
}
mymodel.filefield.storage.object_parameters.update(options_dict)
mymodel.filefield.save()
2。使用 boto3
手动上传文件另一种选择是使用 boto3
客户端手动上传文件(Documentation with the upload_fileobj 方法。
然后您可以使用以下摘自 this answer 的代码设置对象元数据:
import boto3
s3 = boto3.resource('s3')
options_dict = {"Metadata": {"metadata1": "ImageName",
"metadata2": "ImagePROPERTIES",
"metadata3": "ImageCREATIONDATE"}
s3.upload_fileobj(file, bucketname, key, ExtraArgs=options_dict)
之后,您必须将 FileField 的 name
属性 设置为 S3 Bucket 中的键,如 this answer.
object.filefield.name = 'file/key/in/bucket'