Flask应用如何生成不含服务器目录结构的流式Zip文件
Flask生成不含服务器目录结构的Zip文件解决方案
核心问题是你往Zip包中添加文件时,默认使用了服务器上的完整文件路径作为压缩包内的路径。解决关键是指定压缩包内的文件名(即arcname参数),只保留文件本身的名称而非完整路径。
以下是两种可行的实现方案:
方案一:直接指定arcname为文件名
使用zipfile.ZipFile.write()方法时,通过arcname参数明确设置压缩包内的文件名称,只保留原始文件名即可。
from flask import Flask, send_file import zipfile import os from io import BytesIO app = Flask(__name__) @app.route('/download-images') def download_images(): # 替换为你的图片目录路径 target_dir = '/dir/to/the/files' # 在内存中创建Zip文件,避免写入服务器磁盘 zip_buffer = BytesIO() with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zipf: # 遍历目标目录下的所有文件 for root, _, files in os.walk(target_dir): for file in files: # 筛选图片文件,可根据需求调整后缀 if file.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')): full_file_path = os.path.join(root, file) # 关键:用arcname指定压缩包内仅保留文件名 zipf.write(full_file_path, arcname=file) # 将缓冲区指针移到文件开头,确保send_file能正确读取 zip_buffer.seek(0) # 返回Zip文件给用户 return send_file( zip_buffer, mimetype='application/zip', as_attachment=True, download_name='images.zip' ) if __name__ == '__main__': app.run(debug=True)
方案二:切换工作目录后添加文件
先切换到目标图片目录,再添加文件,此时使用相对路径即可避免带上服务器的完整路径,适合批量处理目录下所有文件的场景。
from flask import Flask, send_file import zipfile import os from io import BytesIO app = Flask(__name__) @app.route('/download-images') def download_images(): target_dir = '/dir/to/the/files' zip_buffer = BytesIO() # 保存当前工作目录,后续恢复避免影响其他逻辑 original_work_dir = os.getcwd() try: # 切换到目标图片目录 os.chdir(target_dir) with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zipf: # 遍历当前目录(.)下的所有文件 for root, _, files in os.walk('.'): for file in files: if file.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')): relative_path = os.path.join(root, file) # 仅保留文件名,若需要保留子目录结构可去掉os.path.basename zipf.write(relative_path, arcname=os.path.basename(relative_path)) finally: # 恢复原工作目录 os.chdir(original_work_dir) zip_buffer.seek(0) return send_file( zip_buffer, mimetype='application/zip', as_attachment=True, download_name='images.zip' ) if __name__ == '__main__': app.run(debug=True)
注意事项
- 如果目标目录下存在同名文件(比如不同子目录下有相同文件名的图片),直接使用文件名会导致压缩包内文件被覆盖。这种情况可以给文件名添加前缀(比如子目录名),或者在遍历过程中检查并跳过重复文件。
- 使用
BytesIO在内存中生成Zip文件,避免在服务器磁盘上创建临时文件,节省磁盘资源且更高效。
内容的提问来源于stack exchange,提问作者James Watson
相关产品推荐
相关产品推荐

