Rust 接入阿里云 OSS 断点上传下载:rusty-cat 直连模式实战

适合读者:想在 Rust 后端服务、内部 CLI、可信 Worker 中直接把大文件上传到阿里云 OSS,或从 OSS 断点下载文件的开发者。

1. 先说结论:直连模式只适合可信环境

rusty-cat 支持阿里云 OSS direct 模式,也就是运行 Rust 程序的进程直接持有阿里云 AccessKey,并在本地为 OSS 请求签名。

这个模式适合:

  • 后端服务。
  • 内部运维 CLI。
  • 私有化部署 Worker。
  • CI/CD 或数据处理任务。

不适合:

  • 桌面客户端直接内置 AccessKey Secret。
  • 移动 App 直接内置 AccessKey Secret。
  • 浏览器或公开分发的软件。

原因很简单:**AccessKey Secret 是长期密钥,一旦放到用户机器里,就有被提取的风险。**如果是用户侧应用,建议看下一篇"阿里云 OSS 预签名上传下载",让后端签发短期 URL,客户端只拿临时授权。

本文不会出现任何真实 AccessKey、Secret、Bucket 或业务地址。示例全部使用环境变量和占位名称,复制运行前请替换为你自己的安全配置。

2. rusty-cat 在 OSS 直连模式里解决什么?

如果你自己手写 OSS 分片上传,需要处理:

  • 创建 multipart upload。
  • 按分片上传 part。
  • 查询已上传 part 以支持恢复。
  • 所有 part 成功后 complete multipart upload。
  • 取消时清理 multipart session。
  • 下载时对 HEAD 和 Range GET 加 OSS 签名。
  • 每个分片失败后的重试。
  • 上传/下载进度回调。
  • 多任务并发控制。

rusty-cat 把通用调度交给 MeowClient,把阿里云 OSS 签名和 multipart 细节封装到:

  • AliOssDirectUpload
  • AliOssDirectDownload

你要做的是:准备配置、构造任务、注入 OSS 协议插件、提交任务。

3. 依赖与 feature

如果使用 GitHub 当前发布文档中的版本,可以这样写:

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

如果你的项目基于本地源码 0.1.1,核心 API 写法基本一致,但正式接入时仍建议以 crates.iodocs.rs 对应版本为准:

aliyun-oss-direct feature 会启用阿里云 OSS 直连签名相关能力。生产环境不要为了省事直接启用 all,只打开自己需要的 provider feature。

4. 需要哪些参数?

阿里云 OSS 直连上传和下载都需要这些值:

参数 示例 是否敏感 说明
bucket my-bucket OSS Bucket 名称。
access_key_id 从环境变量读取 阿里云 AccessKey ID。不要写死在代码里。
access_key_secret 从环境变量读取 阿里云 AccessKey Secret。绝对不要提交到 Git。
region cn-beijing Bucket 所在区域。
object_key uploads/demo.bin OSS 对象路径。
object_url https://{bucket}.oss-{region}.aliyuncs.com/{object_key} 通常否 目标对象 URL。不要在 URL 里拼接密钥。

推荐通过环境变量读取密钥:

bash 复制代码
export ALIYUN_ACCESS_KEY_ID="REDACTED_ACCESS_KEY_ID"
export ALIYUN_ACCESS_KEY_SECRET="REDACTED_ACCESS_KEY_SECRET"

上面只是占位写法。文章、截图、日志和 Git 仓库里只应该出现变量名或 REDACTED,不应该出现真实值。

5. OSS 直连上传完整示例

下面示例展示如何上传本地 ./demo.bin 到 OSS。

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

use rusty_cat::aliyun_oss_direct::AliOssDirectUpload;
use rusty_cat::api::{MeowClient, MeowConfig, UploadPounceBuilder};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let bucket = "my-bucket";
    let region = "cn-beijing";
    let object_key = "uploads/demo.bin";

    let access_key_id = std::env::var("ALIYUN_ACCESS_KEY_ID")?;
    let access_key_secret = std::env::var("ALIYUN_ACCESS_KEY_SECRET")?;

    let object_url = format!(
        "https://{bucket}.oss-{region}.aliyuncs.com/{object_key}"
    );

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

    let upload_protocol = AliOssDirectUpload::new(
        bucket,
        access_key_id,
        access_key_secret,
        region,
    );

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

    let outcome = client
        .enqueue_and_wait(task, |record| {
            println!(
                "OSS 上传进度: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 必须存在。
  • my-bucketcn-beijinguploads/demo.bin 要替换成你自己的 Bucket、Region 和对象路径。
  • 环境变量必须设置,不能把 AccessKey Secret 直接写到源码里。
  • Bucket 权限要允许对应 AccessKey 执行 multipart upload、list parts、complete multipart upload 等操作。

6. 上传参数逐个解释

代码 说明
MeowConfig::builder().max_upload_concurrency(1) 控制同时运行的上传任务组数量。初次接入建议从 1 开始,避免并发过高影响 OSS 或本地磁盘。
AliOssDirectUpload::new(bucket, access_key_id, access_key_secret, region) 创建阿里云 OSS 直连上传协议对象。密钥只保存在内存中的协议对象里,SDK 不会替你写入数据库。
UploadPounceBuilder::new(file_name, file_path, chunk_size) 创建上传任务。chunk_size 单位是字节,1024 * 1024 表示 1 MiB。
with_url(object_url) 设置 OSS 对象最终 URL。直连协议会从 URL 中识别对象路径。
with_breakpoint_upload(Arc::new(upload_protocol)) 把阿里云上传协议注入任务。需要 Arc,因为后台执行器可能跨 async task 使用协议对象。
with_max_chunk_retries(3) 单个分片失败后最多额外重试 3 次。
enqueue_and_wait(...) 提交任务并等待完成。CLI 或简单程序推荐先用它。
client.close().await 显式关闭后台调度器,生产代码不要省略。

7. OSS 直连下载完整示例

下载时使用 AliOssDirectDownload。SDK 会执行 HEAD 获取大小,再用 Range GET 下载分片,provider 插件会为请求添加 OSS 签名。

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

use rusty_cat::aliyun_oss_direct::AliOssDirectDownload;
use rusty_cat::api::{DownloadPounceBuilder, MeowClient, MeowConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let bucket = "my-bucket";
    let region = "cn-beijing";
    let object_key = "uploads/demo.bin";

    let access_key_id = std::env::var("ALIYUN_ACCESS_KEY_ID")?;
    let access_key_secret = std::env::var("ALIYUN_ACCESS_KEY_SECRET")?;

    let object_url = format!(
        "https://{bucket}.oss-{region}.aliyuncs.com/{object_key}"
    );

    let client = MeowClient::new(MeowConfig::default());
    let download_protocol = AliOssDirectDownload::new(
        bucket,
        access_key_id,
        access_key_secret,
        region,
    );

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

    let outcome = client
        .enqueue_and_wait(task, |record| {
            println!(
                "OSS 下载进度: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 目录要存在,或者由业务代码提前创建。
  • AccessKey 要有读取该对象的权限。
  • 本地日志不要打印 access_key_secret

8. 直连模式的安全清单

检查项 建议
密钥来源 使用环境变量、密钥管理服务或部署平台 Secret,不要写死在代码里。
Git 提交 检查 .env、配置文件、测试脚本,避免把密钥提交到仓库。
日志 不打印 AccessKey Secret,不打印包含敏感签名信息的完整调试内容。
数据库 传输表里只存 credential_ref,不要存原始 Secret。
权限 AccessKey 使用最小权限,只允许目标 Bucket 和必要操作。
客户端 公开客户端不要使用 direct 模式,改用预签名 URL。
轮换 定期轮换 AccessKey,并确保服务能平滑加载新密钥。

9. 如何和业务数据库配合?

rusty-cat 不内置数据库。你可以在自己的数据库里保存:

  • 业务文件 ID。
  • 本地路径。
  • OSS bucketregionobject_key
  • 传输方向:upload / download。
  • 分片大小。
  • 传输状态和进度。
  • 凭证引用:例如 credential_ref

不要保存:

  • access_key_secret 原文。
  • 可以长期访问资源的敏感 URL。
  • 未脱敏的调试日志。

进程重启后,读取未完成任务,重新构造 AliOssDirectUploadAliOssDirectDownload,再调用 try_enqueue(...)enqueue_and_wait(...)

10. 常见问题排查

现象 常见原因 处理建议
返回 403 AccessKey 错误、权限不足、Region 错误、机器时间偏差。 检查 Bucket、Region、RAM 权限、本机时间。
上传后对象不可见 multipart complete 失败或任务未真正完成。 看 complete callback 和错误日志,不要只看分片上传成功。
下载无法获取文件大小 HEAD 请求权限不足或签名失败。 检查读取权限和 OSS 对象 URL。
分片反复重试 网络不稳定、chunk_size 不合适、OSS 限流。 调整 chunk_size,降低并发,查看 OSS 服务端日志。
程序退出后任务状态丢失 业务没有持久化任务状态。 在进度回调中异步写入自己的数据库。

11. 本篇小结

阿里云 OSS 直连模式的优点是后端接入简单、传输链路直接、SDK 能本地处理签名和 multipart 流程。它的前提是运行环境可信,能够安全持有 AccessKey。

如果你的 Rust 程序运行在服务端或内部环境,AliOssDirectUploadAliOssDirectDownload 是很直接的选择。如果程序运行在用户机器上,不要把 Secret 放进去,下一篇的预签名 URL 模式会更合适。

相关推荐
十五年专注C++开发1 小时前
QtFluentWidgets: 一套基于C++ Qt Widgets的Fluent Design风格控件库
开发语言·c++·qt·qtfluentwidgets
Arman_1 小时前
01 Rust 大文件断点上传下载入门:用 rusty-cat 让上传下载更可靠
http·https·rust·tokio·大量阅读·文件分片上传下载
江屿风1 小时前
【c++笔记】类和对象流食般投喂(下)
开发语言·c++·笔记
踩着两条虫10 小时前
「AI + 低代码」的可视化设计器
开发语言·前端·低代码·设计模式·架构
JoneBB10 小时前
ABAP Webservice连接
运维·开发语言·数据库·学习
即使再小的船也能远航11 小时前
【Python】安装
开发语言·python
Irissgwe11 小时前
类与对象(三)
开发语言·c++·类和对象·友元
雪度娃娃12 小时前
转向现代C++——优先选用nullptr而不是0和NULL
开发语言·c++
zyk_computer12 小时前
AI 时代,或许 Rust 比 Python 更合适
人工智能·后端·python·ai·rust·ai编程·vibe coding