侧边栏壁纸
博主头像
AI研究僧

hycj89@163.com

  • 累计撰写 1,899 篇文章
  • 累计创建 179 个标签
  • 累计收到 1 条评论
标签搜索

目 录CONTENT

文章目录

django自定义文件存储系统并限制上传文件大小

AI研究僧
2019-06-01 / 0 评论 / 0 点赞 / 408 阅读 / 607 字

需求说明

项目中有上传文件的需求,同时又想限制上传文件的大小,对于超过100mb的文件拒绝上传

django的settings文件设置

...
MEDIA_URL="/media/"  # 访问文件的url根路径
MEDIA_ROOT=os.path.join(BASE_DIR, "media")  # 文件存储根目录,可自行修改要保存的位置
MAX_FILE_SIZE = 104857600  # 限制最大文件100MB
...

自定义文件存储系统

在django的应用目录下(或其他位置)新建文件 storage.py,代码如下:

class FileTooLarge(Exception):
    """
    限制上传文件大小异常,可单独创建exception.py文件保存该类
    """

class LiterDocStorage(FileSystemStorage):
	# location和base_url均可自定义,定义后settings中的设置就会失效,不建议在这里修改
    def __init__(self, location=settings.MEDIA_ROOT, base_url=settings.MEDIA_URL):
        # 初始化,location
        super(LiterDocStorage, self).__init__(location, base_url)

    def _save(self, name, content):
        """重写限制文件大小为100MB"""
        if content.size > settings.MAX_FILE_SIZE:
            raise FileTooLarge('文件应小于%sMB' % int((settings.MAX_FILE_SIZE / (1024 * 1024))))
        return super(LiterDocStorage, self)._save(name, content)

注意这里对文件大小的判断是不能通过self.size(name)获取的,这个方法是在视图函数中获取文件对象后调用的,file.size属性调用的该方法

通过调试输出 content 的类型,发现它是一个 InMemoryUploadedFiledjango.core.files.uploaderdfile 中,定位源代码如下:

class InMemoryUploadedFile(UploadedFile):
    """
    A file uploaded into memory (i.e. stream-to-memory).
    """
    def __init__(self, file, field_name, name, content_type, size, charset, content_type_extra=None):
        super().__init__(file, name, content_type, size, charset, content_type_extra)
        self.field_name = field_name

    def open(self, mode=None):
        self.file.seek(0)
        return self

    def chunks(self, chunk_size=None):
        self.file.seek(0)
        yield self.read()

    def multiple_chunks(self, chunk_size=None):
        # Since it's in memory, we'll never have multiple chunks.
        return False

可以在__init__方法中看到有属性 size,因此通过 content.size 得到文件大小,单位是byte

models中的设置

class MyModel(models.Model):
    upload = models.FileField(upload_to='uploads/', storage=LiterDocStorage())  # 这里指定文件存储类型是自定义类

视图函数中使用

file = request.FILES.get('file')  # 前端发送的文件
try:
	MyModel.objects.create(upload=file)
except FileTooLarge as e:  # 限制文件上传大小为100MB
    code = 1
    msg = '文件上传失败,%s' % str(e)	

参考:
FileField

Managing files

FileSystemStorage

编写一个自定义存储系统

博主关闭了所有页面的评论