在Django中保留FileField的原始文件名

时间:2014-11-04 05:06:23

标签: django django-models django-file-upload

我想在Django中保留UploadedFile的原始文件名,其位置存储在FileField中。现在我观察到,如果两个文件具有相同的名称,则上传的第一个文件保留其原始名称,但第二次上载具有该名称的文件时,会附加一个随机字符串以使文件名唯一。一种解决方案是向模型添加其他字段:Django: How to save original filename in FileField?Saving Original File Name in Django with FileField但这些解决方案似乎不是最理想的,因为它们需要更改Model字段。

另一种方法是在文件前面添加一个随机目录路径,确保在给定目录中文件名是唯一的,并允许basename保持不变。一种方法是传入一个可调用的upload_to来做到这一点。另一种选择是子类FileField并覆盖get_filename以不将输入文件名剥离到basename,允许调用者传入带有前置路径的文件名。如果我想使用ImageField,那么后一种选择并不理想,因为我也必须将其子类化。

3 个答案:

答案 0 :(得分:1)

在查看the code that actually generates the unique filename by appending the random string时,看起来这个问题的最佳解决方案可能是使用subclass the Storage class in-use和override get_available_name方法通过预先添加目录而不是发布来创建唯一的文件名 - 将字符串添加到基本名称。

答案 1 :(得分:0)

对不起快速回答,这是您提出问题的另一种方法: 这里的想法是为每个上传的文件创建一个唯一的文件夹。

# in your settings.py file
MY_FILE_PATH = 'stored_files/'

路径是您的文件将被存储: / public / media / stored_files

# somewhere in your project create an utils.py file
import random
try:
    from hashlib import sha1 as sha_constructor
except ImportError:
    from django.utils.hashcompat import sha_constructor


def generate_sha1(string, salt=None):
    """
    Generates a sha1 hash for supplied string.

    :param string:
        The string that needs to be encrypted.

    :param salt:
        Optionally define your own salt. If none is supplied, will use a random
        string of 5 characters.

    :return: Tuple containing the salt and hash.

    """
    if not isinstance(string, (str, unicode)):
         string = str(string)
    if isinstance(string, unicode):
        string = string.encode("utf-8")
    if not salt:
        salt = sha_constructor(str(random.random())).hexdigest()[:5]
    hash = sha_constructor(salt+string).hexdigest()

    return (salt, hash)

在models.py

from django.conf import settings
from utils.py import generate_sha1

def upload_to_unqiue_folder(instance, filename):
    """
    Uploads a file to an unique generated Path to keep the original filename
    """

    salt, hash = generate_sha1('{}{}'.format(filename, get_datetime_now().now))

    return '%(path)s%(hash_path)s%(filename)s' % {'path': settings.MY_FILE_PATH,
                                               'hash_path': hash[:10],
                                               'filename': filename}



#And then add in your model fileField the uplaod_to function
class MyModel(models.Model):
    file = models.FileField(upload_to=upload_to_unique_folder)

该文件将上传到此位置:

公开/媒体/ stored_file_path / unique_hash_folder / my_file.extention

注意:我从Django userena来源获取了代码,并根据我的需要进行了调整

注意2:有关更多信息,请查看关于Django文件上传的这个greate帖子:File upload example

祝你有个美好的一天。

编辑:尝试提供有效的解决方案:)

答案 2 :(得分:-2)

据我了解,在表单提交/文件上传过程中,您可以添加表单验证功能。

在验证和清理过程中,您可以检查数据库是否已经没有重复的名称(即查询是否存在该文件名)。

如果重复,您可以将其重命名为xyz_1,xyz_2等