【问题标题】:Django/Python: How to read a file and validate that it is an audio file? [duplicate]Django/Python:如何读取文件并验证它是音频文件? [复制]
【发布时间】:2012-12-25 05:49:27
【问题描述】:

可能重复:
Django (audio) File Validation

我正在构建一个网络应用程序,用户可以在其中上传媒体内容,包括音频文件。

我的 AudioFileUploadForm 中有一个干净的方法可以验证以下内容:

  • 音频文件不是太大。
  • 音频文件具有有效的 content_type(MIME 类型)。
  • 音频文件具有有效的扩展名。

但是,我担心安全性。用户可以上传带有恶意代码的文件,并轻松通过上述验证。我接下来要做的是验证音频文件确实是一个音频文件(在它写入磁盘之前)。

我应该怎么做?

class UploadAudioForm(forms.ModelForm):
    audio_file = forms.FileField()

    def clean_audio_file(self):
        file = self.cleaned_data.get('audio_file',False):
            if file:
                if file._size > 12*1024*1024:
                    raise ValidationError("Audio file too large ( > 12mb )")
                if not file.content_type in ['audio/mpeg','audio/mp4', 'audio/basic', 'audio/x-midi', 'audio/vorbis', 'audio/x-pn-realaudio', 'audio/vnd.rn-realaudio', 'audio/x-pn-realaudio', 'audio/vnd.rn-realaudio', 'audio/wav', 'audio/x-wav']:
                    raise ValidationError("Sorry, we do not support that audio MIME type. Please try uploading an mp3 file, or other common audio type.")
                if not os.path.splitext(file.name)[1] in ['.mp3', '.au', '.midi', '.ogg', '.ra', '.ram', '.wav']:
                    raise ValidationError("Sorry, your audio file doesn't have a proper extension.")
                # Next, I want to read the file and make sure it is 
                # a valid audio file. How should I do this? Use a library?
                # Read a portion of the file? ...?
                if not ???.is_audio(file.content):
                    raise ValidationError("Not a valid audio file.")
                return file
            else:
                raise ValidationError("Couldn't read uploaded file")

编辑:通过“验证音频文件确实是音频文件”,我的意思是:

包含音频文件典型数据的文件。我担心用户可能会上传带有适当标题的文件和恶意脚本来代替音频数据。例如... mp3 文件是 mp3 文件吗?或者它是否包含一些不属于 mp3 文件的内容?

【问题讨论】:

  • 定义有效的音频文件?
  • 使用服务器端病毒扫描程序
  • @AamirAdnan 不是这样。如果您阅读了您所引用问题的答案,您会看到回答者不知道使用哪个过程来读取和进一步验证音频文件......因此未完成该部分。事实上,他明确表示“我不知道最好的库是什么”。我的问题是,我应该使用什么库或方法来做到这一点。

标签: python django file audio file-upload


【解决方案1】:

另一个已发布的答案的替代方法 header 解析。这意味着有人仍然可以在有效标头后面包含其他数据。

是对整个文件进行验证,这会消耗更多的 CPU 但也有更严格的策略。可以做到这一点的库是python audiotools,相关的API方法是AudioFile.verify

这样使用:

import audiotools

f = audiotools.open(filename)
try:
    result = f.verify()
except audiotools.InvalidFile:
    # Invalid file.
    print("Invalid File")
else:
    # Valid file.
    print("Valid File")

警告是这个verify 方法非常严格,实际上可以将编码错误的文件标记为无效。您必须自己决定这是否适合您的用例。

【讨论】:

  • +1,来自 Plone 世界,无论如何,这为验证文件类型提供了一些宝贵的一般见解,谢谢 Wessie!
【解决方案2】:

这个想法是使用诸如sndhdr之类的实用程序来尝试读取文件的标题。

from sndhdr import what
import os
from settings import MEDIA_ROOT
...
if what( os.path.join( MEDIA_ROOT, file.name ) ) == None:
# header parse failed, so, it could be a non-audio file.

在这种情况下,您必须确保该实用程序无法将非音频文件识别为音频文件。

我从不使用 sndhdr 实用程序,因此,使用另一个可能会更好。比如还有mutagen项目。

更新

更专业的方法。

  1. 让用户上传他的文件而不进行此类验证。
  2. 创建与一个文件关联的特殊模型字段:is_checked。设置字段 默认为假。
  3. 不要让其他用户下载有 is_checked == 假
  4. 组织一个异步任务来运行 检查未检查文件的反恶意软件。该软件必须是 从您的 pythonic 任务中作为函数调用。该功能必须 回答问题:特定文件是否包含恶意软件部分。
  5. 如果当前文件有恶意软件部分,删除它并删除有关该恶意软件的记录 文件。否则从您的任务中设置 is_checked = True。

为什么是分开的任务?因为这样的恶意软件检查可能是一个很长的操作。

【讨论】:

  • 引用上面问题中的代码,file.content_type 已经读取了 header,然后返回 header 中列出的 content-type。但是 Django 文档说这还不够:(docs.djangoproject.com/en/dev/topics/http/file-uploads/…)。使用 sndhdr 会简单地复制 file.content_type 所做的事情吗?
  • @sgarza62 我认为Django使用了你的浏览器发送的内容类型。
  • 感谢您的回答。这是一种有趣的方法,但是,我查看了源代码,并且 sndhdr 无法识别 mp3、realaudio 以及其他常见的音频类型。
  • @sgarza62 我已经更新了我的答案。请看。
  • 伟大的更新。唯一的问题(对于这种特定情况)是我需要在写入磁盘之前运行该操作,因为我们的 Web 应用程序实时呈现上传的内容。我认为您在更新中提供的信息将对其他用户有所帮助。
猜你喜欢
  • 2011-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-27
  • 1970-01-01
相关资源
最近更新 更多