You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django邮件自动化发送小体积PDF附件显示0字节问题修复

Django邮件发送PDF附件0字节问题修复

问题表现

  • 基于Django开发邮件自动发送功能时,发送的PDF附件文件名可正常显示,但文件大小为0字节,无实际内容无法打开
  • 异常存在明确的大小分界特征:发送约3MB的较大PDF文件可正常送达,1~2MB的较小PDF文件发送后必然出现0字节问题
  • 调试阶段直接打印上传的media文件对象,可正常输出对应PDF的文件名

问题根因

核心是文件读取指针的位置处理逻辑错误:

  1. 代码中为了计算文件大小,执行media.seek(0, os.SEEK_END)将文件读取指针移动到了文件末尾,调用media.tell()拿到文件大小后,没有将指针重置回文件起始位置
  2. 后续执行media.read()读取附件内容时,默认从当前指针位置(也就是文件末尾)开始读取,最终得到空字节流,挂载到邮件里的附件自然是0字节
  3. 3MB大文件可正常发送,是因为Django默认对大于2.5MB的上传文件采用临时文件存储(TemporaryUploadedFile),读取时存在隐式的指针重置逻辑,属于偶发正常;1~2MB的小文件走内存存储(InMemoryUploadedFile),无隐式重置逻辑,因此稳定触发空读问题。

修复方案

关键修复步骤:获取完文件大小后,新增一行media.seek(0)将文件指针重置到文件起始位置,再执行附件内容读取

修正后的完整视图代码如下:

import os
from django.http import HttpResponse
from django.shortcuts import render
from django.core.mail import EmailMessage
# 此处保留原有项目的模型、表单引入逻辑
# from .forms import BeastForm
# from .models import Beast

def addbeast(request):
    if request.method == 'POST':
        form = BeastForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            name  = form.cleaned_data['name']
            media = form.cleaned_data['media']
            
            # 获取文件大小
            media.seek(0, os.SEEK_END)
            filesize = media.tell()
            print(filesize)
            # 修复:重置文件指针到开头,避免后续读取为空
            media.seek(0)
            
            subject = "NDA IS Attached"
            message = "NDA Attachment from " + name 
            
            sender = "-----@gmail.com"
            cc_myself = True
            cc_mail = "----!!!!!!@gmail.com"

            recipients = ['9999999999@gmail.com']
            if cc_myself:
                recipients.append(cc_mail)

            try:
                mail = EmailMessage(subject, message, sender, recipients)
                mail.attach(media.name, media.read(), media.content_type)
                mail.send()
                return HttpResponse("FORM SUBMISSION IS SUCCESSFUL")
            except Exception as e:
                # 打印异常信息便于排查问题,不要裸except吞掉所有错误
                print(f"Mail send failed: {str(e)}")
                return HttpResponse('no success')
    else:
        form = BeastForm()

    return render(request, "post_list.html", {
        "form": form
    })

额外优化建议

  • 禁止使用裸except捕获所有异常,建议明确捕获异常类型并打印错误日志,避免发送失败时无法定位具体原因
  • 如果附件已经保存到服务器本地存储,可直接使用EmailMessage的attach_file()方法传入文件本地路径读取附件,无需手动处理文件指针,能减少类似问题出现

内容的提问来源于stack exchange,提问作者Heeket Mehta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 09:36:18