上传文件至S3遇boto.exception.S3ResponseError:400错误,求排查
分析你的S3上传错误及代码问题
你遇到的S3ResponseError: 400 Bad Request(HTTP请求解析错误),大概率是压缩文件未正确生成就被上传,或是文件路径处理不当导致的。我们来逐一排查代码里的问题:
1. ZipFile未正确关闭,导致压缩文件不完整
你创建ZipFile的方式是zipfile.ZipFile(zipname, mode='w').write(...),这种一次性调用的写法会让ZipFile对象执行完write后没有被正确关闭——操作系统可能还没把所有数据写入磁盘,你就开始读取上传了,导致S3收到不完整的压缩文件,进而触发解析错误。
2. 压缩文件时的路径冗余
你已经执行了os.chdir(UPLOAD_FOLDER),当前工作目录已经切换到上传文件夹,此时write方法里的os.path.join(UPLOAD_FOLDER, filename)会生成重复的路径(比如/upload/path/upload/path/file.txt)。虽然这不一定直接引发400错误,但会让压缩包内的文件路径变得混乱,不符合预期。
修正后的代码
file = request.files["wg_puid"] filename = hash + ".wargamerpl2" zipname = hash + ".zip" # 用完整路径保存文件,避免依赖工作目录 file_path = os.path.join(UPLOAD_FOLDER, filename) file.save(file_path) # 使用上下文管理器确保ZipFile正确关闭,同时启用压缩 with zipfile.ZipFile(os.path.join(UPLOAD_FOLDER, zipname), mode='w', compression=zipfile.ZIP_DEFLATED) as zip_ref: # arcname指定压缩包内的文件名,避免冗余路径 zip_ref.write(file_path, arcname=filename) # 删除原文件 if os.path.exists(file_path): os.remove(file_path) else: return apology("Something went wrong", 400) # 上传到S3 key = boto.s3.key.Key(bucket, zipname) with open(os.path.join(UPLOAD_FOLDER, zipname), "rb") as f: key.send_file(f) # 可选:上传完成后清理本地压缩文件 zip_path = os.path.join(UPLOAD_FOLDER, zipname) if os.path.exists(zip_path): os.remove(zip_path)
额外优化建议
- 尽量避免使用
os.chdir,它会改变全局工作目录,可能影响后续其他文件操作,直接使用完整路径更安全可靠。 - 添加
compression=zipfile.ZIP_DEFLATED启用压缩(默认是无压缩的打包),能大幅减少上传文件的大小,提升传输效率。 - 上传完成后记得删除本地的压缩文件,避免服务器磁盘空间被不必要占用。
内容的提问来源于stack exchange,提问作者user9740954
相关产品推荐
相关产品推荐

