适合读者:想在 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获取大小,再用 RangeGET分片读取。 - 对每个请求进行 Shared Key 签名。
- 管理进度、重试、暂停、恢复、取消。
rusty-cat 把通用任务调度交给 MeowClient,把 Azure 签名和 block blob 逻辑封装到:
AzureBlobDirectUploadAzureBlobDirectDownload
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.io 和 docs.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_ACCOUNT和AZURE_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 直连模式内部流程
上传侧:
- SDK 根据
chunk_size切分本地文件。 AzureBlobDirectUpload对 Put Block 请求做 Shared Key 签名。- 每个分片作为一个 block 上传。
- 所有 block 成功后,提交 Put Block List。
- 任务完成,进度回调进入
Complete。
下载侧:
- SDK 准备下载任务。
AzureBlobDirectDownload为HEAD请求加签,获取 Blob 大小。- SDK 根据大小和
chunk_size生成 Range 请求。 - provider 为 Range
GET请求加签。 - 分片写入本地文件,并通过回调通知进度。
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 下发到客户端。