我在 Cloud Run 上运行,并设置了从 Flask 到浏览器的流式传输。它似乎可以很好地传输二进制数据(在本例中它已被腌制和压缩)。
def transmit_binary_data(N): # Yield compressed data in chunks
chunk_size = 16384 # Maybe too small?
print("Start transmitting compressed:", N, "chunk size:", chunk_size)
for i in range(0, N, chunk_size):
yield e[i:i+chunk_size]
with app.app_context():
response = make_response(Response(transmit_binary_data(content_length),
mimetype="application/octet-stream"))
response.headers['Content-Length'] = content_length
return response
在 javascript 方面,我在块进来时累积它们,然后解压缩和解泡。完美。
但它不适用于非常大(GB)的数据集。我收到日志错误:
textPayload: "Response size was too large. Please consider reducing response size."
我认为可能发生的情况是 Cloud Run 在服务器和客户端之间创建了一个中间缓冲区,而该缓冲区太大了。
或者也许错误在于我天真地告诉 Cloud Run 最终将发送多少数据:::
response.headers['Content-Length'] = content_length
?
感谢建议。
好吧,是的,我搞砸了:如果您将
['Content-Length']
设置为标头,那么 Cloud Run 实际上会假设您不想流式传输数据,即使 mime 类型设置为流式传输也是如此。哎呀。
但是我想要一个下载进度条,这意味着浏览器需要在开始下载之前知道长度。我创建了一个新的标头变量
[x-total-length]
并将其设置为字节总数。
response = make_response(Response(transmit_binary_data(content_length), mimetype="application/octet-stream"))
response.headers['x-total-length'] = content_length
# DONT DO THIS:: response.headers['Content-Length'] = content_length
流媒体开始完美运行。除了进度条不起作用。结果是为了使
[x-total-length]
对浏览器可见,我必须编辑 Flask 的 _init_.py
使其成为有效条目:
@app.after_request
def after_request(response):
# Access-Control-Allow-Origin Stuff...:
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
response.headers.add('Access-Control-Expose-Headers', 'x-total-length') #for streaming data
现在一切正常了。