您无需将文件保存到服务器。您可以将文件下载到内存中,然后构建一个
Response包含该文件的对象。
from flask import Flask, Responsefrom boto3 import clientapp = Flask(__name__)def get_client(): return client( 's3', 'us-east-1', aws_access_key_id='id', aws_secret_access_key='key' )@app.route('/blah', methods=['GET'])def index(): s3 = get_client() file = s3.get_object(Bucket='blah-test1', Key='blah.txt') return Response( file['Body'].read(), mimetype='text/plain', headers={"Content-Disposition": "attachment;filename=test.txt"} )app.run(debug=True, port=8800)小文件也可以,对于用户来说,没有任何有意义的等待时间。但是,对于较大的文件,这会严重影响UX。该文件将需要完全下载到服务器,然后再下载给用户。因此,要解决此问题,请使用方法的
Range关键字参数
get_object:
from flask import Flask, Responsefrom boto3 import clientapp = Flask(__name__)def get_client(): return client( 's3', 'us-east-1', aws_access_key_id='id', aws_secret_access_key='key' )def get_total_bytes(s3): result = s3.list_objects(Bucket='blah-test1') for item in result['Contents']: if item['Key'] == 'blah.txt': return item['Size']def get_object(s3, total_bytes): if total_bytes > 1000000: return get_object_range(s3, total_bytes) return s3.get_object(Bucket='blah-test1', Key='blah.txt')['Body'].read()def get_object_range(s3, total_bytes): offset = 0 while total_bytes > 0: end = offset + 999999 if total_bytes > 1000000 else "" total_bytes -= 1000000 byte_range = 'bytes={offset}-{end}'.format(offset=offset, end=end) offset = end + 1 if not isinstance(end, str) else None yield s3.get_object(Bucket='blah-test1', Key='blah.txt', Range=byte_range)['Body'].read()@app.route('/blah', methods=['GET'])def index(): s3 = get_client() total_bytes = get_total_bytes(s3) return Response( get_object(s3, total_bytes), mimetype='text/plain', headers={"Content-Disposition": "attachment;filename=test.txt"} )app.run(debug=True, port=8800)这将以1MB的块下载文件,并在下载文件时将其发送给用户。这两个
.txt文件均已通过40MB文件进行了测试。



