Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中为文件名(AmazonS3)添加动态内容配置_Python_Django_Amazon Web Services_Amazon S3_Django Storage - Fatal编程技术网

在python中为文件名(AmazonS3)添加动态内容配置

在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

我有一个Django模型,它将文件名保存为“uuid4().pdf”。其中uuid4为创建的每个实例生成一个随机uuid。此文件名也以相同的名称存储在AmazonS3服务器上

我试图为上传到AmazonS3的文件名添加一个自定义配置,这是因为每当我下载文件而不是uuid文件时,我都希望看到一个自定义名称。同时,我希望文件以uuid文件名存储在s3上

因此,我使用的是Python2.7。我已尝试在如下设置中添加内容\u处置:

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。这就是为什么需要我投票的原因。