在python中为文件名(AmazonS3)添加动态内容配置
我有一个Django模型,它将文件名保存为“uuid4().pdf”。其中uuid4为创建的每个实例生成一个随机uuid。此文件名也以相同的名称存储在AmazonS3服务器上 我试图为上传到AmazonS3的文件名添加一个自定义配置,这是因为每当我下载文件而不是uuid文件时,我都希望看到一个自定义名称。同时,我希望文件以uuid文件名存储在s3上 因此,我使用的是Python2.7。我已尝试在如下设置中添加内容\u处置:在python中为文件名(AmazonS3)添加动态内容配置,python,django,amazon-web-services,amazon-s3,django-storage,Python,Django,Amazon Web Services,Amazon S3,Django Storage,我有一个Django模型,它将文件名保存为“uuid4().pdf”。其中uuid4为创建的每个实例生成一个随机uuid。此文件名也以相同的名称存储在AmazonS3服务器上 我试图为上传到AmazonS3的文件名添加一个自定义配置,这是因为每当我下载文件而不是uuid文件时,我都希望看到一个自定义名称。同时,我希望文件以uuid文件名存储在s3上 因此,我使用的是Python2.7。我已尝试在如下设置中添加内容\u处置: AWS_CONTENT_DISPOSITION = 'core.util
AWS_CONTENT_DISPOSITION = 'core.utils.s3.get_file_name'
其中get_file_name()返回文件名
我还尝试将此添加到设置中:
AWS_HEADERS = {
'Content-Disposition': 'attachments; filename="%s"'% get_file_name(),
}
不走运
你们中有谁知道如何实现这一点。我猜你们正在使用来自django存储的S3BotoStorage,所以在将文件上载到S3时,覆盖模型的save()方法,并在那里设置头 下面我举一个例子:
class ModelName(models.Model):
sthree = S3BotoStorage()
def file_name(self,filename):
ext = filename.split('.')[-1]
name = "%s/%s.%s" % ("downloads", uuid.uuid4(), ext)
return name
upload_file = models.FileField(upload_to=file_name,storage = sthree)
def save(self):
self.upload_file.storage.headers = {'Content-Disposition': 'attachments; filename="%s"' %self.upload_file.name}
super(ModelName, self).save()
django storages的S3boto3存储的当前版本支持
AWS\u S3\u对象\u参数
global settings变量,该变量还允许修改ContentDisposition
。但问题是,它会按原样应用于上传到s3的所有对象,而且会影响使用存储的所有模型,这可能不是预期的结果
下面的黑客对我有用
from storages.backends.s3boto3 import S3Boto3Storage
class DownloadableS3Boto3Storage(S3Boto3Storage):
def _save_content(self, obj, content, parameters):
"""
The method is called by the storage for every file being uploaded to S3.
Below we take care of setting proper ContentDisposition header for
the file.
"""
filename = obj.key.split('/')[-1]
parameters.update({'ContentDisposition': f'attachment; filename="{filename}"'})
return super()._save_content(obj, content, parameters)
在这里,我们覆盖存储对象的本机保存方法,并确保在每个文件上设置了正确的内容配置。
对于courese,您需要将此存储提供给正在处理的字段:
my_file_filed = models.FileField(upload_to='mypath', storage=DownloadableS3Boto3Storage())
如果有人像我一样发现了这一点:上面提到的所有解决方案在Django3.0中都不适用于我
S3Boto3Storage
的Docstring建议覆盖S3Boto3Storage.get\u object\u参数
,但是此方法仅接收上载文件的名称
,此时该文件已由upload\u更改为
,可能与原始文件不同
有效的方法如下:
S3BOTO3类客户存储(S3BOTO3存储):
“”“覆盖某些上载参数,如ContentDisposition标头。”“”
定义、获取、写入参数(自身、名称、内容):
“”“使用原始文件名设置ContentDisposition头。
docstring建议为此重写'get_object_parameters',
`get_object_parameters`只获取一个不是原始文件名的`name`,
但是“上传到”的结果。
"""
params=super()。\u获取\u写入\u参数(名称、内容)
原始名称=getattr(内容“名称”,无)
如果原始名称和名称!=原名:
内容处置=附件;filename=“{original_name}”
参数['ContentDisposition']=内容处理
返回参数
然后在文件字段中使用此存储,例如:
文件\字段=models.FileField(
上传到=一些函数,
存储=S3Boto3CustomStorage(),
)
无论您提出了什么解决方案,都不要直接更改
file\u field.storage.object\u参数
(例如,在模型的save()
中,正如在一个类似问题中所建议的那样),因为这将更改ContentDisposition
头,以便后续上载使用相同存储的任何字段的文件。这可能不是您想要的。只有在使用s3botostrage
时,才可以调整此选项以有条件地设置标题。有了它,您可以轻松地创建测试,而不必关心S3。这就是为什么需要我投票的原因。