Rust 接入微软 Azure Blob 文件上传下载:rusty-cat 直连模式实战

适合读者:想在 Rust 后端服务或内部工具中,把大文件断点上传到 Microsoft Azure Blob Storage,或从 Azure Blob 断点下载文件的开发者。

1. 先说安全边界:Account Key 不能放到公开客户端

Azure Blob direct 模式使用 Storage Account Key 做 Shared Key 签名。也就是说,运行 rusty-cat 的进程会持有 Azure 存储账号密钥。

这个模式适合:

  • 后端服务。
  • 内部 CLI。
  • 私有 Worker。
  • 数据迁移或备份任务。

不适合:

  • 桌面客户端内置 Account Key。
  • 移动 App 内置 Account Key。
  • 浏览器或公开分发的二进制里写死密钥。

Storage Account Key 通常权限很大,一旦泄露,影响范围可能非常严重。用户侧客户端建议使用 SAS URL,也就是下一篇会讲的 Azure Blob 预签名文件上传下载。

本文不会写任何真实 account_key、连接字符串或 SAS token。示例统一使用环境变量和占位路径。

2. rusty-cat 在 Azure Blob 直连模式里做什么?

Azure Block Blob 大文件上传不是简单一次 PUT 就完事。你通常需要:

  • 把文件切成多个 block。
  • 对每个 block 调用 Put Block。
  • 生成稳定的 block id。
  • 所有 block 上传后调用 Put Block List 提交。
  • 恢复时识别已上传 block。
  • 下载时使用 HEAD 获取大小,再用 Range GET 分片读取。
  • 对每个请求进行 Shared Key 签名。
  • 管理进度、重试、暂停、恢复、取消。

rusty-cat 把通用任务调度交给 MeowClient,把 Azure 签名和 block blob 逻辑封装到:

  • AzureBlobDirectUpload
  • AzureBlobDirectDownload

3. 依赖与 feature

toml 复制代码
[dependencies]
rusty-cat = { version = "0.2.2", features = ["azure-blob-direct"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }

版本提示:如果你本地源码版本是 0.1.1,核心 API 与本文示例接近;正式项目请以 crates.iodocs.rs 对应版本为准:

4. 需要哪些参数?

Azure Blob 直连上传/下载常用参数:

参数 示例 是否敏感 说明
account_name mystorageaccount Azure Storage Account 名称。
account_key 从环境变量读取 Storage Account Key,高敏感密钥。
container files Blob Container 名称。
blob_name uploads/demo.bin Blob 路径。
blob_url https://{account}.blob.core.windows.net/{container}/{blob_name} 通常否 Blob 最终 URL。

推荐使用环境变量:

bash 复制代码
export AZURE_STORAGE_ACCOUNT="你的账号名"
export AZURE_STORAGE_KEY="你的 Account Key"

不要把 Account Key 写进:

  • 源码。
  • README。
  • CSDN 文章截图。
  • GitHub Actions 日志。
  • 数据库传输表。
  • 客户端配置文件。

5. Azure Blob 直连上传完整示例

rust 复制代码
use std::sync::Arc;

use rusty_cat::api::{MeowClient, MeowConfig, UploadPounceBuilder};
use rusty_cat::azure_blob_direct::AzureBlobDirectUpload;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let account_name = std::env::var("AZURE_STORAGE_ACCOUNT")?;
    let account_key = std::env::var("AZURE_STORAGE_KEY")?;

    let container = "files";
    let blob_name = "uploads/demo.bin";
    let blob_url = format!(
        "https://{account_name}.blob.core.windows.net/{container}/{blob_name}"
    );

    let config = MeowConfig::builder()
        .max_upload_concurrency(1)
        .build()?;
    let client = MeowClient::new(config);

    let upload_protocol = AzureBlobDirectUpload::new(
        account_name,
        account_key,
    );

    let task = UploadPounceBuilder::new(
        "demo.bin",
        "./demo.bin",
        1024 * 1024,
    )
    .with_url(blob_url)
    .with_breakpoint_upload(Arc::new(upload_protocol))
    .with_max_chunk_retries(3)
    .build()?;

    let outcome = client
        .enqueue_and_wait(task, |record| {
            println!(
                "Azure 上传进度:file={} progress={:.2}% status={:?}",
                record.file_name(),
                record.progress() * 100.0,
                record.status(),
            );
        })
        .await?;

    println!("上传完成:task_id={} payload={:?}", outcome.task_id, outcome.payload);
    client.close().await?;
    Ok(())
}

运行前确认:

  • ./demo.bin 存在。
  • Container 已创建。
  • AZURE_STORAGE_ACCOUNTAZURE_STORAGE_KEY 已通过安全方式注入。
  • Account Key 有写入目标 container/blob 的权限。

6. 上传参数逐个解释

参数或方法 说明
AzureBlobDirectUpload::new(account_name, account_key) 创建 Azure 直连上传协议对象,用 Shared Key 给请求签名。
UploadPounceBuilder::new(file_name, file_path, chunk_size) 创建上传任务。chunk_size 单位是字节。
with_url(blob_url) 设置最终 Blob URL。provider 会在内部构造 Put Block 和 Put Block List 请求。
with_breakpoint_upload(Arc::new(upload_protocol)) 注入 Azure 上传协议。
with_max_chunk_retries(3) 分片失败后的额外重试次数。
max_upload_concurrency(1) 控制上传任务组并发。初次接入建议保守配置。

Azure Block Blob 对 block 大小和 block 数量有平台限制。大文件上传时,chunk_size 不能只凭感觉设置,要结合 Azure 当前限制、文件大小和业务并发压测。

7. Azure Blob 直连下载完整示例

rust 复制代码
use std::sync::Arc;

use rusty_cat::api::{DownloadPounceBuilder, MeowClient, MeowConfig};
use rusty_cat::azure_blob_direct::AzureBlobDirectDownload;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let account_name = std::env::var("AZURE_STORAGE_ACCOUNT")?;
    let account_key = std::env::var("AZURE_STORAGE_KEY")?;

    let container = "files";
    let blob_name = "uploads/demo.bin";
    let blob_url = format!(
        "https://{account_name}.blob.core.windows.net/{container}/{blob_name}"
    );

    let client = MeowClient::new(MeowConfig::default());
    let download_protocol = AzureBlobDirectDownload::new(
        account_name,
        account_key,
    );

    let task = DownloadPounceBuilder::new(
        "demo.bin",
        "./downloads/demo.bin",
        1024 * 1024,
        blob_url,
    )
    .with_breakpoint_download(Arc::new(download_protocol))
    .with_max_chunk_retries(3)
    .build();

    let outcome = client
        .enqueue_and_wait(task, |record| {
            println!(
                "Azure 下载进度:file={} progress={:.2}% status={:?}",
                record.file_name(),
                record.progress() * 100.0,
                record.status(),
            );
        })
        .await?;

    println!("下载完成:task_id={}", outcome.task_id);
    client.close().await?;
    Ok(())
}

运行前确认:

  • ./downloads 目录存在。
  • Blob URL 指向真实存在的对象。
  • Account Key 有读取目标 Blob 的权限。

8. Azure 直连模式内部流程

上传侧:

  1. SDK 根据 chunk_size 切分本地文件。
  2. AzureBlobDirectUpload 对 Put Block 请求做 Shared Key 签名。
  3. 每个分片作为一个 block 上传。
  4. 所有 block 成功后,提交 Put Block List。
  5. 任务完成,进度回调进入 Complete

下载侧:

  1. SDK 准备下载任务。
  2. AzureBlobDirectDownloadHEAD 请求加签,获取 Blob 大小。
  3. SDK 根据大小和 chunk_size 生成 Range 请求。
  4. provider 为 Range GET 请求加签。
  5. 分片写入本地文件,并通过回调通知进度。

9. 安全清单

检查项 建议
Account Key 只在可信服务端或内部工具使用。
环境变量 使用部署平台 Secret、KMS、Key Vault 或环境变量注入。
源码 不要把 Account Key 写入 Rust 文件、配置样例或测试常量。
日志 不打印 Account Key,不打印包含敏感认证信息的请求头。
数据库 只保存 credential_ref,运行时再解析真实密钥。
客户端 公开客户端改用 SAS URL,不使用 direct。
权限 使用最小权限策略,不要给无关 container/blob 权限。

10. 和 Azure SAS 模式怎么选?

模式 优点 风险 适合
direct 后端接入简单,SDK 本地签名,少一次后端 URL 签发流程。 Account Key 泄露风险高,不适合公开客户端。 后端服务、内部工具。
SAS 长期密钥留在后端,客户端只拿短期 URL。 后端需要签发和刷新 SAS。 桌面端、移动端、多租户应用。

如果你不确定选哪个,按这个原则:

  • 程序在自己服务器上跑:可以考虑 direct。
  • 程序发给用户运行:优先 SAS。

11. 常见问题排查

现象 常见原因 处理建议
403 认证失败 Account Key 错误、账号名错误、时间偏差、URL 格式错误。 检查账号、Key、Blob URL、本机时间。
上传后 Blob 不可读 Put Block List 没有成功提交。 检查 complete callback、错误日志和 Azure Portal。
block 数量过多 chunk_size 太小,导致分片数超过限制。 增大 chunk_size
单个 block 太大 chunk_size 超过 Azure 限制。 调小 chunk_size 并参考 Azure 官方限制。
恢复失败 业务没有保存足够的任务元数据。 保存 blob URL、方向、chunk_size、状态、credential_ref。

12. 本篇小结

Azure Blob direct 模式适合可信环境中的 Rust 程序。rusty-cat 负责分片、调度、重试、进度和生命周期,AzureBlobDirectUpload / AzureBlobDirectDownload 负责 Shared Key 签名和 Blob 协议细节。

如果你的程序部署在服务端,这个模式接入成本低;如果你的程序运行在用户设备上,请使用下一篇的 SAS 预签名模式,不要把 Account Key 下发到客户端。

相关推荐
冴羽yayujs2 小时前
前端周报:Rolldown 1.0 正式发布、TanStack 遭遇史诗级供应链攻击、Bun 全面迁移至 Rust
前端·rust·前端开发·前端周报
techdashen2 小时前
Rust 能帮你捕获什么,又不能捕获什么
开发语言·后端·rust
带娃的IT创业者2 小时前
Rewrite Bun in Rust:一次前端工具链的底层重构实践入门指南
前端·重构·rust·bun·运行时·前端工具链
Arman_2 小时前
Rust 接入阿里云 OSS 断点上传下载:rusty-cat 直连模式实战
开发语言·阿里云·rust·oss断点续传
Arman_2 小时前
01 Rust 大文件断点上传下载入门:用 rusty-cat 让上传下载更可靠
http·https·rust·tokio·大量阅读·文件分片上传下载
zyk_computer12 小时前
AI 时代,或许 Rust 比 Python 更合适
人工智能·后端·python·ai·rust·ai编程·vibe coding
Rust语言中文社区14 小时前
【Rust日报】2026-05-14 Pyrefly v1.0 正式发布:快速的 Python 类型检查器和语言服务器
开发语言·后端·python·rust
不可食用盐16 小时前
# AI开发基于 Tauri 2 + React 的所见即所得 Markdown 编辑器
react.js·rust·ai编程
江晓曼*凡云基地17 小时前
Hermes Agent 多Agent模式:并行拆解复杂任务的实战指南
javascript·windows·microsoft