Потоковая передача (загрузка) файла из хранилища BLOB-объектов Azure пользователю через flask

Я написал этот фрагмент кода, который загружает файл из учетной записи хранения Azure, а затем отправляет его пользователю. Однако сначала он должен полностью загрузить файл, а затем отправить его пользователю. можно ли «передать» файл в потоковом режиме, чтобы загрузка (на стороне пользователя) начиналась немедленно, и файл не нужно было сохранять на сервере.

Прежде чем кто-то предложит использовать ссылку Azure с токеном SAR, позвольте мне сказать вам, что мне не разрешено использовать токены SAR.

@forecasting_bp.route("/api/download/", methods=["GET"])
def download():
    """"""
    report = request.args.get("report")
    config_id = request.args.get("config_id")
    extension = request.args.get("extension", ".csv")
    filename = f"{report}{config_id}{extension}"
    blobpath = f"{config_id}/{filename}"
    with open(filename, "wb") as my_blob:
        download_stream = blob_client.download_blob()
        my_blob.write(download_stream.readall())
    return send_file(
        filename,
        as_attachment=True,
        download_name=filename,
    )

🤔 А знаете ли вы, что...
Flask отличается простотой и минимализмом, позволяя разработчикам выбирать и интегрировать необходимые компоненты.


106
1

Ответ:

Решено

Я преобразовал свои комментарии в ответ, чтобы помочь сообществу.

Я попробовал приведенный ниже код, чтобы загрузить файл из хранилища BLOB-объектов Azure пользователю через Flask. Вот мой репозиторий Github с полным кодом.

Код:

просмотры.py:

import os
from flask import Blueprint, request, Response
from .azure_blob import get_blob_client

forecasting_bp = Blueprint('forecasting_bp', __name__)

def stream_blob(blob_client, chunk_size=1024*1024):
    """Generator function to stream the blob in chunks."""
    blob_size = blob_client.get_blob_properties().size
    start = 0

    while start < blob_size:
        end = min(start + chunk_size, blob_size)
        download_stream = blob_client.download_blob(offset=start, length=chunk_size)
        chunk = download_stream.readall()
        yield chunk
        start = end

@forecasting_bp.route("/api/download/", methods=["GET"])
def download():
    connection_string = os.getenv("AZURE_STORAGE_CONNECTION_STRING")
    container_name = os.getenv("AZURE_STORAGE_CONTAINER_NAME")
    
    report = request.args.get("report")
    config_id = request.args.get("config_id")
    extension = request.args.get("extension", ".csv")
    filename = f"{report}{config_id}{extension}"
    blobpath = f"{config_id}/{filename}"

    blob_client = get_blob_client(connection_string, container_name)
    blob_client = blob_client.get_blob_client(blob=blobpath)

    response = Response(
        stream_blob(blob_client, chunk_size=1024*1024),
        content_type='application/octet-stream',
        headers = {
            "Content-Disposition": f"attachment; filename = {filename}"
        }
    )

    return response

.env:

AZURE_STORAGE_CONNECTION_STRING = "<storage_conneString>"
AZURE_STORAGE_CONTAINER_NAME = "<container_name>"

Выход :

Вывод браузера:

http://127.0.0.1:5001/api/download/?report=sample_report&config_id=123&extension=.csv