使用django强制使用唯一的上传文件名?

时间:2010-04-20 08:30:57

标签: python django pinax file-rename

在使用django上传服务器时,使用服务器上的唯一文件名重命名照片的最佳方法是什么?我想确保每个名称只使用一次。是否有任何pinax应用程序可以执行此操作,可能使用GUID?

7 个答案:

答案 0 :(得分:125)

使用uuid。要将其与模型联系起来,请参阅Django documentation了解FileField upload_to。

例如,在models.py中定义以下函数:

import uuid
import os

def get_file_path(instance, filename):
    ext = filename.split('.')[-1]
    filename = "%s.%s" % (uuid.uuid4(), ext)
    return os.path.join('uploads/logos', filename)

然后,在定义FileField / ImageField时,请将get_file_path指定为upload_to值。

file = models.FileField(upload_to=get_file_path,
                        null=True,
                        blank=True,
                        verbose_name=_(u'Contact list'))

答案 1 :(得分:9)

在Django 1.6.6,1.5.9和1.4.14之前,get_avaialable_name函数会通过添加下划线自动为文件指定唯一名称。因此,例如,如果您将一个文件“test.jpg”和另一个文件“test.jpg”保存到您的服务器,第一个将被称为test.jpg,第二个将被称为test_1.jpg。

唉,结果是DDOS一台机器的向量,通过发送数千个零字节文件进行存储,每个文件检查数千个以前的文件,看看它的名字应该是什么。

正如您see in the docs所示,新系统会在下划线后面添加七个随机数字来解决此问题。

答案 2 :(得分:9)

更好的方法是在helpers.py中使用公共类。这样您就可以在应用程序中重复使用随机文件生成器。

在helpers.py中:

import os
import uuid
from django.utils.deconstruct import deconstructible


@deconstructible
class RandomFileName(object):
    def __init__(self, path):
        self.path = os.path.join(path, "%s%s")

    def __call__(self, _, filename):
        # @note It's up to the validators to check if it's the correct file type in name or if one even exist.
        extension = os.path.splitext(filename)[1]
        return self.path % (uuid.uuid4(), extension)

然后在你的模型中导入辅助类:

from mymodule.helpers import RandomFileName 

然后使用它:

logo = models.ImageField(upload_to=RandomFileName('logos'))

参考:https://coderwall.com/p/hfgoiw/give-imagefield-uploads-a-unique-name-to-avoid-file-overwrites

答案 3 :(得分:2)

在撰写此答案时,您似乎不再需要做任何特别的事情来实现这一目标。如果你设置一个带有静态upload_to属性的FileField,Django存储系统将自动管理命名,这样如果上传了重复的文件名,Django将为副本随机生成一个新的唯一文件名。

适用于Django 1.10。

答案 4 :(得分:0)

如何将文件名与上传照片的日期/时间连接,然后使用hashlib创建消息摘要?这应该给你独特的文件名。

或者,您可以重复使用创建唯一文件名的a neat little snippet,然后使用该文件的完整路径作为哈希调用的输入。这为您提供了可以映射到文件的唯一恒定长度字符串。

答案 5 :(得分:0)

django自动执行唯一文件名。 如果文件已经存在,则在文件名后附加七个唯一字符

在django 2.2上测试

答案 6 :(得分:0)

您可以编写自己的FileField,也可以重写generate_filename

例如:

class UniqueNameFileField(FileField):
    def generate_filename(self, instance, filename):
        _, ext = os.path.splitext(filename) 
        name = f'{uuid.uuid4().hex}{ext}'
        return super().generate_filename(instance, name)