Django发送压缩XLS文件附件失败问题咨询
我来帮你排查下问题,以及给出修复方案:
问题出在哪?
你在压缩文件时的操作犯了两个关键错误:
- 复用了存储Excel内容的
StringIO对象f:当用zipfile.ZipFile(f, mode='w')打开这个对象时,写模式会直接清空f里原来的Excel数据,后续你再调用f.getvalue()拿到的已经不是你要压缩的Excel内容了。 - 没有处理
StringIO的指针位置:就算你先拿到了Excel内容,写完zip后如果不把指针移到开头,邮件附件可能会读取到空内容(虽然getvalue()不受指针影响,但这是个容易踩的坑)。
修复后的完整代码
正确的做法是用两个独立的StringIO对象分别存储Excel和压缩后的zip数据,避免互相干扰:
import xlwt import StringIO import zipfile from django.core.mail import EmailMessage work_book = xlwt.Workbook() # 此处为Excel相关处理逻辑... report_name = "do_something_%(username)s_%(current_date)s.xls" # 第一步:把Excel内容写入单独的StringIO excel_buffer = StringIO.StringIO() work_book.save(excel_buffer) excel_content = excel_buffer.getvalue() # 先把Excel内容存下来,避免后续被覆盖 # 初始化邮件对象 message = EmailMessage( subject=u"Sample Title", body=u"Sample body", to=["test@company.com"]) # 第二步:创建新的StringIO来生成zip文件 zip_buffer = StringIO.StringIO() with zipfile.ZipFile(zip_buffer, mode='w', compression=zipfile.ZIP_DEFLATED) as zf: # 将之前保存的Excel内容写入zip包,用原来的xls文件名 zf.writestr(report_name, excel_content) # 写完zip后,把指针移到缓冲区开头(getvalue()其实不受影响,但养成习惯更稳妥) zip_buffer.seek(0) # 附加zip文件到邮件,最好指定MIME类型让客户端正确识别 report_name_zip = 'do_something_%(username)s_%(current_date)s.zip' message.attach(report_name_zip, zip_buffer.getvalue(), 'application/zip') message.send()
几个关键细节
- 分离缓冲区:用
excel_buffer存Excel数据,zip_buffer存压缩后的数据,彻底避免数据被覆盖的问题。 - 指定MIME类型:附加zip时加上
application/zip类型,邮件客户端能直接识别这是压缩文件,不会出现无法打开的情况。 - 指针位置处理:写入数据后调用
seek(0)是IO操作的常规操作,虽然StringIO.getvalue()会返回全部内容,但如果后续改用read()方法就必须这么做,提前养成习惯能减少踩坑。
这样修改后,你应该就能正常收到带压缩Excel附件的邮件了。
内容的提问来源于stack exchange,提问作者ë..
相关产品推荐
相关产品推荐

