66

使用 django 在服务器上使用唯一文件名重命名照片的最佳方法是什么?我想确保每个名称只使用一次。是否有任何 pinax 应用程序可以做到这一点,也许使用 GUID?

4

7 回答 7

158

使用 uuid。要将其绑定到您的模型中,请参阅FileField upload_to 的Django 文档

例如,在您的 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_pathupload_to值。

file = models.FileField(upload_to=get_file_path,
                        null=True,
                        blank=True,
                        verbose_name=_(u'Contact list'))
于 2010-04-20T18:00:37.250 回答
20

更好的方法是在你的 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

于 2016-10-24T00:38:23.163 回答
9

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

唉,这原来是对机器进行 DDOS 攻击的向量,通过向其发送数千个零字节文件进行存储,每个文件检查数千个以前的文件以查看其名称应该是什么。

正如您将在文档中看到的那样,新系统在下划线后附加了七个随机数字来解决此问题。

于 2010-04-20T16:26:14.293 回答
7

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

适用于 Django 1.10。

于 2017-04-10T17:50:06.583 回答
1

您可以自己编写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)
于 2020-03-21T14:56:22.400 回答
0

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

或者,您可以重新使用一个简洁的小片段来创建唯一的文件名,然后使用该文件的完整路径作为哈希调用的输入。这为您提供了唯一的恒定长度字符串,您可以将其映射到您的文件。

于 2010-04-20T09:08:48.057 回答
0

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

在 django 2.2 上测试

于 2019-08-12T16:39:58.157 回答