基于Python Magic的Django文件验证问题:文件扩展名验证报错排查
问题分析与修复方案
看起来你遇到的验证错误主要来自三个核心问题:MIME类型格式错误、验证规则与需求不匹配,以及文件指针未重置。我来帮你逐一解决:
1. 错误的MIME类型定义
你当前写的application/.mov、application/.png这类MIME格式完全不符合标准。每种文件类型都有对应的官方MIME类型,比如:
- MP4视频:
video/mp4 - JPG图片:
image/jpeg - PNG图片:
image/png - MP3音频:
audio/mpeg - ZIP压缩包:
application/zip
错误的MIME类型会导致magic库返回的真实类型和你定义的不匹配,直接触发验证错误。
2. Video模型验证规则与需求不符
你提到Video模型仅接受MP4格式,但当前validate_is_video里只允许.mov后缀和对应的MIME类型,这和你的需求完全相反,需要调整为MP4的验证规则。
3. 文件指针未重置
调用file.read(1024)读取文件头部后,文件指针会停在1024字节的位置,后续Django处理文件时会无法读取完整内容,甚至引发额外错误。需要在读取后用file.seek(0)重置指针。
修复后的validators.py代码
import os import magic from django.core.exceptions import ValidationError def validate_is_video(file): # 修正:MP4的标准MIME类型和后缀 valid_mime_types = ['video/mp4'] file_mime_type = magic.from_buffer(file.read(1024), mime=True) # 重置文件指针 file.seek(0) if file_mime_type not in valid_mime_types: raise ValidationError('Sorry,Cannot accept unsupported file type.') valid_file_extensions = ['.mp4'] ext = os.path.splitext(file.name)[1] if ext.lower() not in valid_file_extensions: raise ValidationError('Sorry,Cannot accept unacceptable file extension.') def validate_is_image(file): # 修正:图片的标准MIME类型 valid_mime_types = ['image/png', 'image/jpeg'] file_mime_type = magic.from_buffer(file.read(1024), mime=True) file.seek(0) if file_mime_type not in valid_mime_types: raise ValidationError('Sorry,Cannot accept unsupported file type.') valid_file_extensions = ['.png', '.jpg', '.jpeg'] # 补充jpeg后缀兼容 ext = os.path.splitext(file.name)[1] if ext.lower() not in valid_file_extensions: raise ValidationError('Sorry,Cannot accept unacceptable file extension.') def validate_is_audio(file): # 修正:音频的标准MIME类型 valid_mime_types = ['audio/mpeg', 'audio/wav'] file_mime_type = magic.from_buffer(file.read(1024), mime=True) file.seek(0) if file_mime_type not in valid_mime_types: raise ValidationError('Sorry,Cannot accept unsupported file type.') valid_file_extensions = ['.mp3', '.wav'] ext = os.path.splitext(file.name)[1] if ext.lower() not in valid_file_extensions: raise ValidationError('Sorry,Cannot accept unacceptable file extension.') def validate_is_file(file): # 修正:压缩包的标准MIME类型 valid_mime_types = ['application/zip', 'application/vnd.rar'] file_mime_type = magic.from_buffer(file.read(1024), mime=True) file.seek(0) if file_mime_type not in valid_mime_types: raise ValidationError('Sorry,Cannot accept unsupported file type.') valid_file_extensions = ['.zip', '.rar'] ext = os.path.splitext(file.name)[1] if ext.lower() not in valid_file_extensions: raise ValidationError('Sorry,Cannot accept unacceptable file extension.')
额外说明
- 我在图片验证里补充了
.jpeg后缀,因为有些工具保存的jpg文件会用这个后缀,提升兼容性; - RAR的标准MIME类型是
application/vnd.rar,不是application/.rar,这个也需要修正; - 每次读取文件头部后都加上
file.seek(0),确保后续Django能正常处理上传的文件。
替换完代码后,再测试上传MP4视频、JPG/PNG图片,应该就能正常通过验证了。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

