背景 在Flask中对文件进行归档并下载时,一般会使用zipfile库。由于zipfile库必须先生成zip文件再进行下载,所以当生成的zip文件较多且较大时,会逐渐消耗磁盘的容量。为了避免这种情况,我们可以使用zipstream库。
使用zipstream库 zipstream可以不生成zip文件,直接下载:
1 2 3 4 5 6 7 8 @app.route('/package.zip' , methods=['GET' ], endpoint='zipball' ) def zipball (): z = zipstream.ZipFile(mode='w' , compression=ZIP_DEFLATED) z.write('/path/to/file' ) response = Response(z, mimetype='application/zip' ) response.headers['Content-Disposition' ] = 'attachment; filename={}' .format ('files.zip' ) return response
使用生成器的方式进行流式下载:
1 2 3 4 5 6 7 8 9 10 11 @app.route('/package.zip' , methods=['GET' ], endpoint='zipball' ) def zipball (): def zip_generator (): z = zipstream.ZipFile(mode='w' , compression=ZIP_DEFLATED) z.write('/path/to/file' ) for chunk in z: yield chunk response = Response(generator(), mimetype='application/zip' ) response.headers['Content-Disposition' ] = 'attachment; filename={}' .format ('files.zip' ) return response
以迭代器的形式生成zip文件,避免将大文件存储在内存中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @app.route('/package.zip' , methods=['GET' ], endpoint='zipball' ) def zipball (): def read_file (path ): with open (path, 'rb' ) as f: while True : data = f.read(20 * 1024 * 1024 ) if not data: break yield data def zip_generator (): z = zipstream.ZipFile(mode='w' , compression=ZIP_DEFLATED) z.write_iter('arcname' , read_file('/path/to/file' )) for chunk in z: yield chunk response = Response(generator(), mimetype='application/zip' ) response.headers['Content-Disposition' ] = 'attachment; filename={}' .format ('files.zip' ) return response
参考文档 python-zipstream github