在现代Web应用中,文件上传和显示功能是常见的需求。本文将介绍如何使用Flask作为后端和Flutter作为前端来实现一个文件上传到Azure Blob Storage并在前端显示的完整流程。

环境准备

首先,我们需要确保以下环境配置:

  • Python 3.7+
  • Flutter SDK
  • Azure存储账户
  • 安装必要的Python库:flask, flask_cors, azure-storage-blob
pip install flask flask_cors azure-storage-blob

Flask后端配置

1. 配置Azure存储

我们首先在Flask中配置Azure Blob Storage的连接:

from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient, generate_blob_sas, BlobSasPermissions

connect_str = 'DefaultEndpointsProtocol=CONNECTION_STRING_ETC'
container_name = "documents"
blob_service_client = BlobServiceClient.from_connection_string(conn_str=connect_str)
container_client = blob_service_client.create_container(container_name)

2. 定义上传路由

定义一个上传文件的路由,处理文件上传到Azure Blob Storage:

@app.route('/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return jsonify({"message": "No file available", "status": "fail"}), 400
    file = request.files['file']
    if file.filename == '':
        return jsonify({"message": "No selected file", "status": "fail"}), 400
    if file:
        timestamp = datetime.now().strftime('%Y-%m-%d_%H:%M:%S')
        filename = secure_filename(f"{timestamp}_{file.filename}")
        blob_client = container_client.get_blob_client(filename)
        blob_client.upload_blob(file.stream, overwrite=True)
        file_url = blob_client.url
        return jsonify({"message": "File uploaded successfully", "status": "success", "file_url": file_url}), 200

3. 生成SAS Token

为了安全地访问文件,我们使用SAS Token来生成临时URL:

@app.route('/upload/<path:filename>', methods=['GET'])
def uploaded_file(filename):
    blob_client = container_client.get_blob_client(filename)
    sas_token = generate_blob_sas(
        account_name=blob_service_client.account_name,
        container_name=container_name,
        blob_name=filename,
        account_key=blob_service_client.credential.account_key,
        permission=BlobSasPermissions(read=True),
        expiry=datetime.now(datetime.UTC) + timedelta(hours=1)
    )
    signed_url = f"{blob_client.primary_endpoint}/{container_name}/{blob_client.blob_name}?{sas_token}"
    return jsonify({"file_url": signed_url, "status": "success"})

Flutter前端实现

1. 接收文件URL

在Flutter中,我们需要从Flask获取文件的URL并显示:

Future<void> fetchFile() async {
    setState(() {
        isLoading = true;
    });
    final response = await http.get(Uri.parse('http://127.0.0.1:5000/upload/$filename'));
    if (response.statusCode == 200) {
        var data = jsonDecode(response.body);
        setState(() {
            fileUrl = data['file_url'];
            isLoading = false;
        });
    } else {
        throw Exception('Failed to load file');
    }
}

2. 显示文件

根据文件类型(PDF或图片)选择不同的显示方式:

Widget buildFileWidget() {
    if (isLoading) {
        return Center(child: CircularProgressIndicator());
    } else if (fileUrl != null) {
        if (fileUrl!.toLowerCase().endsWith('.pdf')) {
            return PDF().cachedFromUrl(fileUrl!);
        } else {
            return CachedNetworkImage(
                imageUrl: fileUrl!,
                placeholder: (context, url) => CircularProgressIndicator(),
                errorWidget: (context, url, error) => Icon(Icons.error),
            );
        }
    } else {
        return Center(child: Text('File not found'));
    }
}

调试与问题解决

  • 空白页面问题:检查fileUrl是否正确接收到了URL,确保Azure存储配置正确,CORS设置正确。
  • PDF显示问题:考虑使用flutter_pdfviewsyncfusion_flutter_pdfviewer,注意这些库的平台支持情况。

通过上述步骤,我们可以构建一个功能完备的文件上传和显示系统,利用Flask和Flutter的优势实现跨平台应用的开发。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐