Django文件上传校验:在TemporaryFileUploadHandler块中识别换行符
解决文件上传时按行拆分并检查行长度的问题
看起来你正在处理大文件上传的校验,需要逐行检查每行字符数,还要处理跨chunk的换行问题对吧?我来帮你完善这段代码,解决这些痛点:
完整修改后的代码
from django import forms from django.core.exceptions import ValidationError from django.db import models MAX_LINE_LENGTH = 100 # 这里设置你允许的最大行字符数,可按需调整 class TheModel(models.Model): upload_file = models.FileField(upload_to='the/path') class TheForm(forms.ModelForm): class Meta: model = TheModel fields = ['upload_file'] def clean_upload_file(self): the_file = self.cleaned_data.get('upload_file') if not the_file: return the_file # 用于保存上一个chunk末尾的不完整行,避免跨chunk的行被拆分 leftover = b'' # 兼容Windows(\r\n)和Unix(\n)格式的换行符 newline_patterns = [b'\r\n', b'\n'] for chunk in the_file.chunks(): # 拼接上一个chunk的剩余内容,保证行的完整性 data = leftover + chunk # 统一将Windows换行符替换为Unix格式,方便后续拆分 data = data.replace(b'\r\n', b'\n') # 按换行符拆分内容 lines = data.split(b'\n') # 最后一个元素是当前chunk末尾的不完整行,留到下一个chunk处理 leftover = lines.pop() # 遍历处理每一行 for line_bytes in lines: # 将字节流解码为字符串(假设文件是UTF-8编码,可根据实际情况调整) try: line = line_bytes.decode('utf-8') except UnicodeDecodeError: raise ValidationError("文件包含无效的UTF-8编码字符,请检查文件格式。") # 统计行字符数(若需按字节数统计,直接用len(line_bytes)即可) line_length = len(line) if line_length > MAX_LINE_LENGTH: raise ValidationError(f"发现超过最大长度的行:{line[:20]}...(当前长度{line_length},最大允许{MAX_LINE_LENGTH})") # 处理最后一个chunk剩余的不完整行(如果存在) if leftover: try: final_line = leftover.decode('utf-8') except UnicodeDecodeError: raise ValidationError("文件末尾包含无效的UTF-8编码字符,请检查文件格式。") final_line_length = len(final_line) if final_line_length > MAX_LINE_LENGTH: raise ValidationError(f"文件最后一行超过最大长度:{final_line[:20]}...(当前长度{final_line_length},最大允许{MAX_LINE_LENGTH})") return the_file
关键细节解释
- 跨chunk行处理:用
leftover变量缓存上一个chunk末尾的不完整行,和当前chunk拼接后再拆分,避免把完整的行拆成两段导致漏检或误判。 - 换行符兼容:统一将
\r\n替换为\n,确保不管是Windows还是Unix格式的文件,都能正确拆分每行。 - 编码处理:将二进制字节流解码为字符串,同时捕获编码错误,给用户友好的提示。如果你的文件是其他编码(比如GBK),直接修改
decode的参数即可。 - 大文件友好:借助Django的
chunks()方法分块读取文件,不会一次性把整个大文件加载到内存,避免内存溢出问题。 - 行长度校验:默认按Unicode字符数统计,如果你需要按字节数限制,直接替换成
len(line_bytes)就行。
补充说明
TemporaryFileUploadHandler处理的临时文件确实是以二进制模式打开的,所以我们用字节流处理后再解码的方式是完全正确的。如果需要严格匹配文件原始换行符(不做统一替换),可以先读取文件前几个字节判断换行符类型,再用对应的分隔符拆分,但统一处理的方式更简单通用。
内容的提问来源于stack exchange,提问作者raratiru
相关产品推荐
相关产品推荐

