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

将内存Zip文件对象上传至S3时触发KeyError错误求助

解决内存Zip文件上传S3时的KeyError问题

你遇到的这个KeyError: 'There is no item named 8388608 in the archive'确实挺诡异的,其实背后是两个容易忽略的细节问题,咱们一步步拆解:

错误原因分析

  1. 传错了对象给upload_fileobj:你直接把zipfile.ZipFile实例传给了upload_fileobj,但这个方法需要的是支持read()方法的类文件字节流对象(比如BytesIO、本地文件句柄),而不是ZipFile本身。
  2. 内存Zip未完成收尾+指针位置错误:在写完所有JSON文件到Zip后,你没有关闭ZipFile(这一步会完成Zip文件的目录结构写入等收尾工作),也没有把BytesIO缓冲区的指针移到起始位置。这就导致S3读取到的是不完整、无效的Zip数据,从而触发了莫名其妙的KeyError。

至于本地保存后再上传能正常工作,是因为保存本地时,系统会自动帮你完成ZipFile的关闭操作,重新打开文件时指针默认在开头,自然能正确读取。

修正后的代码

不需要用tempfile,用BytesIO就能高效完成内存Zip上传,只要补上关键步骤:

import boto3
import zipfile
import json
import os
from io import BytesIO  # 别忘了导入BytesIO!

session = boto3.session.Session(
 aws_access_key_id=os.environ.get('AWS_ACCESS_KEY_ID'),
 aws_secret_access_key=os.environ.get('AWS_SECRET_ACCESS_KEY'))
client = session.client('s3')

data = {'test1.json': {'a': 1, 'b': 2}, 'test2.json': {'x': 3, 'y': 4}}

zip_buffer = BytesIO()
# 用with上下文管理器自动关闭ZipFile,避免遗漏收尾操作
with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zf:
    # Python3里用items()替代Python2的iteritems()
    for filename, d in data.items():
        zf.writestr(filename, json.dumps(d, indent=4))

# 将缓冲区指针移到文件开头,确保upload_fileobj能从起始位置读取
zip_buffer.seek(0)

# 传入zip_buffer字节流对象,而不是ZipFile实例
client.upload_fileobj(zip_buffer, os.environ.get('S3_BUCKET'), 'test_zip.zip')

额外优化点

  • 加上zipfile.ZIP_DEFLATED参数可以启用压缩,减少上传的文件大小(如果不需要压缩可以用默认的ZIP_STORED)
  • 用with上下文管理器管理ZipFile,能自动处理关闭操作,比手动调用zf.close()更安全,避免因为代码异常导致的资源泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:52:50