Django 文件存储:为文件名添加密码

Django File Storage: Add passwords to file names

我们使用Python Django。

我想用以下方式存储用户上传的文件:

/<INTEGER>/<HASH>/<FILE>

<INTEGER> 是一个子文件夹,最多可包含 1000 个文件。

<HASH>是每个文件的一个密码,以防止黑客从我们的HTTPS服务器下载别人的其他文件。

<FILE> 是文件名。

如何编写实现此功能的 Django 存储?

首先,我可以从 django.core.files.storage.FileSystemStorage 派生我的 class 还是我需要直接从 django.core.files.storage.Storage 派生?

其次,我应该覆盖哪些方法?我应该覆盖 save 吗?似乎是的,因为最好只在保存时生成哈希,但我不确定我可以在 save 中做我需要的。重写 _save 怎么样?另外:什么是覆盖 get_available_name and/or generate_filename?它们似乎不太适合我的需要,因为最好只在实际保存文件时生成哈希,而不仅仅是在考虑文件名时。

那么,怎么办?

我想你可以有自己的函数来处理你想要创建文件夹结构的方式,你可以在 models.py 中作为
attachment = models.FileField(upload_to=change_file_path,空白=真,空=真)
其中 change_file_path 是您创建所需文件夹结构的自定义函数

同时使用 storageupload_to 参数来设置上传 directory.More 信息 FileField django docs

这里我使用uuid作为<HASH>你可以使用你自己的哈希生成器),max_num是<integer>和senfile在 Django 模型中是 <FILE>

models.py

from django.core.files.storage import FileSystemStorage
import uuid

storeFile = FileSystemStorage(location='SensitiveFiles/')

def content_file_upload(instance, filename):
    return '{0}/{1}/{2}'.format(instance.max_num,str(uuid.uuid4()), filename)

class SensitiveFiles(models.Model):
    user = models.ForeignKey(User)
    senfile = models.FileField(storage=storeFile,upload_to=content_file_upload,validators=[validation_for_max_num_files])
    max_num=models.IntegerField(default=1000)

    def get_file_url(self):
        return self.senfile.url

创建验证器以检查上传目录中的当前文件数。

我会在 django.core.files.storage.FileSystemStorage 中选择 generate_filename。我发现它更合适,因为我在 get_available_name 中仍然有很好的安全垫。 我也不担心在文件未保存的情况下获取文件名,只需要确保哈希生成足够便宜。


# settings.py

DEFAULT_FILE_STORAGE = 'app.storage.CustomStorage'

# app/storage.py

from datetime import datetime
import hashlib
import random

from django.core.files.storage import FileSystemStorage


class CustomStorage(FileSystemStorage):
    def generate_filename(self, filename):
        # implement smarter hash creation method here
        some_hash = hashlib.md5('{}-{}'.format('filename', datetime.now().isoformat())).hexdigest()

        return '{0}/{1}/{2}'.format(random.randint(0, 1000), some_hash, filename)