Django - 获取上传的文件类型/ mimetype

Han*_*pan 16 django

有没有办法在覆盖模型保存方法时获取上传文件的内容类型?我试过这个:

def save(self):
    print(self.file.content_type)
    super(Media, self).save()
Run Code Online (Sandbox Code Playgroud)

但它没有用.在此示例中,self.file是model.FileField:

file = models.FileField(upload_to='uploads/%m-%Y/')
Run Code Online (Sandbox Code Playgroud)

编辑:我希望能够将内容类型保存到数据库,所以在保存实际完成之前我需要它:)

mos*_*krc 27

class MyForm(forms.ModelForm):

    def clean_file(self):
        file = self.cleaned_data['file']
        try:
            if file:
                file_type = file.content_type.split('/')[0]
                print file_type

                if len(file.name.split('.')) == 1:
                    raise forms.ValidationError(_('File type is not supported'))

                if file_type in settings.TASK_UPLOAD_FILE_TYPES:
                    if file._size > settings.TASK_UPLOAD_FILE_MAX_SIZE:
                        raise forms.ValidationError(_('Please keep filesize under %s. Current filesize %s') % (filesizeformat(settings.TASK_UPLOAD_FILE_MAX_SIZE), filesizeformat(file._size)))
                else:
                    raise forms.ValidationError(_('File type is not supported'))
        except:
            pass

        return file
Run Code Online (Sandbox Code Playgroud)

settings.py

TASK_UPLOAD_FILE_TYPES = ['pdf', 'vnd.oasis.opendocument.text','vnd.ms-excel','msword','application',]
TASK_UPLOAD_FILE_MAX_SIZE = "5242880"
Run Code Online (Sandbox Code Playgroud)

  • 我认为除了应该捕获一个AttributeError.否则,不会吞下forms.ValidationError吗? (5认同)
  • 否决:请不要推广信任用户数据**用户数据永远不能被信任**。始终从服务器端源检查文件的类型。 (5认同)
  • 请注意,[`UploadedFile.content_type`](https://docs.djangoproject.com/en/2.1/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.content_type) 来自用户。通常最好使用 [`python-magic`](https://pypi.org/project/python-magic/),或内置 [`imghdr`](/sf/answers/1137690571/ /52499)。 (3认同)
  • 这是一个反模式,应该作为有效答案被删除。请求者可以传入他们想要的任何标头。该文件可以是可执行的,但标题可以表明它是 pdf 并且它可以正常工作。 (3认同)

Pit*_*kos 11

您可以使用 PIL 或魔法来读取前几个字节并以这种方式获取 MIME 类型。我不相信 ,content_type因为任何人都可以伪造 HTTP 标头。

下面的神奇解决方案。对于 PIL 实现,您可以从 django 的get_image_dimensions 中得到一个想法。

import magic


def get_mime_type(file):
    """
    Get MIME by reading the header of the file
    """
    initial_pos = file.tell()
    file.seek(0)
    mime_type = magic.from_buffer(file.read(1024), mime=True)
    file.seek(initial_pos)
    return mime_type
Run Code Online (Sandbox Code Playgroud)

文件是视图中的内存上传文件。

  • 作为这里的一个小帮助者 - 如果您在 Docker 中运行 Python 映像,您需要确保在安装初始依赖项时在 Dockerfile 级别安装 libmagic1。否则 python-magic 将尝试包装尚未安装的系统级库。您可以通过以下命令简单地完成此操作:“RUN apt-get update \ && apt-get install -y curl libmagic1 \ && apt-get -y autoclean”或您当时正在运行的任何其他内容。 (3认同)

Spa*_*man 6

根据文档,处理表单上传的视图代码应该能够获得mimetype(带有警告) request.FILES

拼图的最后一部分是处理来自request.FILES的实际文件数据.此字典中的每个条目都是一个UploadedFile对象 - 一个围绕上传文件的简单包装器.您通常会使用以下方法之一来访问上传的内容:

classUploadedFile除了从File继承的那些之外,所有UploadedFile对象都定义了以下方法/属性:

UploadedFile.content_type随文件上传的内容类型标头(例如text/plain或application/pdf).与用户提供的任何数据一样,您不应相信上传的文件实际上是此类型.您仍然需要验证该文件是否包含内容类型标头声明的内容 - "信任但验证".

这一切都在这里:http://docs.djangoproject.com/en/1.2/topics/http/file-uploads/(虽然我从上面的开发文档剪切了n个粘贴...)

在文档中我根本看不到content_type模型FileField的...