#sdk #cos #cloud-storage #tencent #cloud

cos-rust-sdk

腾讯云对象存储 COS Rust SDK

3 releases

new 0.1.2 Sep 17, 2025
0.1.1 Sep 17, 2025
0.1.0 Sep 17, 2025

#2 in #tencent

MIT license

3MB
1.5K SLoC

腾讯云 COS Rust SDK

Crates.io Documentation License

这是一个用于腾讯云对象存储(COS)的 Rust SDK,提供了完整的 COS API 功能。

特性

  • ✅ 完整的对象存储操作(上传、下载、删除等)
  • ✅ 存储桶管理功能
  • ✅ 腾讯云签名算法实现
  • ✅ 异步支持(基于 tokio)
  • ✅ 类型安全的 API
  • ✅ 详细的错误处理
  • ✅ 支持自定义域名
  • ✅ 支持 HTTPS/HTTP

安装

Cargo.toml 中添加依赖:

[dependencies]
cos-rust-sdk = "0.1.0"
tokio = { version = "1.0", features = ["full"] }

快速开始

基本配置

use cos_rust_sdk::{Config, CosClient, ObjectClient};
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建配置
    let config = Config::new(
        "your-secret-id",
        "your-secret-key",
        "ap-beijing",  // 地域
        "your-bucket-name-1234567890"  // 存储桶名称(包含 APPID)
    )
    .with_timeout(Duration::from_secs(30))
    .with_https(true);

    // 创建客户端
    let cos_client = CosClient::new(config)?;
    let object_client = ObjectClient::new(cos_client.clone());

    Ok(())
}

对象操作

上传对象

// 上传字节数据
let data = b"Hello, COS!";
let response = object_client
    .put_object("test.txt", data.to_vec(), Some("text/plain"))
    .await?;
println!("ETag: {}", response.etag);

// 从文件上传
use std::path::Path;
let response = object_client
    .put_object_from_file("remote-file.jpg", Path::new("local-file.jpg"), None)
    .await?;

下载对象

// 下载到内存
let response = object_client.get_object("test.txt").await?;
println!("Content: {}", String::from_utf8_lossy(&response.data));
println!("Content-Type: {}", response.content_type);

// 下载到文件
use std::path::Path;
object_client
    .get_object_to_file("remote-file.jpg", Path::new("downloaded-file.jpg"))
    .await?;

删除对象

// 删除单个对象
let response = object_client.delete_object("test.txt").await?;

// 批量删除对象
let keys = vec!["file1.txt".to_string(), "file2.txt".to_string()];
let response = object_client.delete_objects(&keys).await?;
for deleted in response.deleted {
    println!("Deleted: {}", deleted.key);
}

获取对象元数据

// 获取对象元数据
let response = object_client.head_object("test.txt").await?;
println!("Size: {} bytes", response.content_length);
println!("Last Modified: {:?}", response.last_modified);

// 检查对象是否存在
let exists = object_client.object_exists("test.txt").await?;
println!("Object exists: {}", exists);

存储桶操作

use cos_rust_sdk::{BucketClient, BucketAcl, ListObjectsV2Options};

let bucket_client = BucketClient::new(cos_client.clone());

// 检查存储桶是否存在
let exists = bucket_client.bucket_exists().await?;

// 列出对象
let options = ListObjectsV2Options {
    prefix: Some("photos/".to_string()),
    max_keys: Some(100),
    ..Default::default()
};
let response = bucket_client.list_objects_v2(Some(options)).await?;
for object in response.contents {
    println!("Key: {}, Size: {}", object.key, object.size);
}

// 设置存储桶 ACL
bucket_client.put_bucket_acl(BucketAcl::PublicRead).await?;

配置选项

基本配置

let config = Config::new(secret_id, secret_key, region, bucket)
    .with_timeout(Duration::from_secs(60))  // 请求超时时间
    .with_https(true)                       // 使用 HTTPS
    .with_domain("custom.domain.com");     // 自定义域名

地域列表

常用地域代码:

  • ap-beijing - 北京
  • ap-shanghai - 上海
  • ap-guangzhou - 广州
  • ap-chengdu - 成都
  • ap-singapore - 新加坡
  • ap-hongkong - 香港

STS 临时凭证

基本用法

use cos_rust_sdk::sts::{StsClient, GetCredentialsRequest, Policy};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建 STS 客户端
    let sts_client = StsClient::new(
        "your-secret-id".to_string(),
        "your-secret-key".to_string(),
        "ap-beijing".to_string(),
    );

    // 创建策略 - 允许读写 media/ 前缀的文件
    let policy = Policy::allow_read_write("your-bucket-1234567890", Some("media/"));

    // 构建请求
    let request = GetCredentialsRequest {
        name: Some("temp-credentials".to_string()),
        policy,
        duration_seconds: Some(3600), // 1小时有效期
    };

    // 获取临时凭证
    let credentials = sts_client.get_credentials(request).await?;
    
    println!("临时 SecretId: {}", credentials.tmp_secret_id);
    println!("临时 SecretKey: {}", credentials.tmp_secret_key);
    println!("SessionToken: {}", credentials.token);
    
    Ok(())
}

Policy 策略配置

预定义策略方法

use cos_rust_sdk::sts::Policy;

// 1. 仅允许上传文件到指定前缀
let upload_policy = Policy::allow_put_object("bucket-1234567890", Some("uploads/"));

// 2. 仅允许下载指定前缀的文件
let download_policy = Policy::allow_get_object("bucket-1234567890", Some("public/"));

// 3. 仅允许删除指定前缀的文件
let delete_policy = Policy::allow_delete_object("bucket-1234567890", Some("temp/"));

// 4. 允许读写操作(上传、下载、删除)到指定前缀
let readwrite_policy = Policy::allow_read_write("bucket-1234567890", Some("media/"));

// 5. 允许读写整个存储桶(不限制前缀)
let full_policy = Policy::allow_read_write("bucket-1234567890", None);

自定义策略

use cos_rust_sdk::sts::{Policy, Statement};
use std::collections::HashMap;

// 创建自定义策略
let custom_policy = Policy::new()
    .add_statement(Statement {
        effect: "allow".to_string(),
        action: vec![
            "name/cos:PutObject".to_string(),
            "name/cos:GetObject".to_string(),
        ],
        resource: vec![
            "qcs::cos:*:uid/1234567890:prefix//1234567890/my-bucket/images/*".to_string()
        ],
        condition: None,
    });

策略使用场景

策略方法 适用场景 权限范围
allow_put_object 前端文件上传 仅上传权限
allow_get_object 公共资源下载 仅下载权限
allow_delete_object 临时文件清理 仅删除权限
allow_read_write 完整文件管理 上传、下载、删除

完整的 STS 示例

use cos_rust_sdk::sts::{StsClient, GetCredentialsRequest, Policy};
use cos_rust_sdk::{Config, CosClient, ObjectClient};
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 获取临时凭证
    let sts_client = StsClient::new(
        "your-secret-id".to_string(),
        "your-secret-key".to_string(),
        "ap-beijing".to_string(),
    );

    let policy = Policy::allow_put_object("bucket-1234567890", Some("uploads/"));
    let request = GetCredentialsRequest {
        name: Some("upload-credentials".to_string()),
        policy,
        duration_seconds: Some(1800), // 30分钟
    };

    let temp_credentials = sts_client.get_credentials(request).await?;

    // 2. 使用临时凭证创建 COS 客户端
    let config = Config::new(
        &temp_credentials.tmp_secret_id,
        &temp_credentials.tmp_secret_key,
        "ap-beijing",
        "bucket-1234567890"
    )
    .with_session_token(&temp_credentials.token)
    .with_timeout(Duration::from_secs(30));

    let cos_client = CosClient::new(config)?;
    let object_client = ObjectClient::new(cos_client);

    // 3. 使用临时凭证上传文件
    let data = b"Hello from temporary credentials!";
    let response = object_client
        .put_object("uploads/temp-file.txt", data.to_vec(), Some("text/plain"))
        .await?;
    
    println!("文件上传成功,ETag: {}", response.etag);
    
    Ok(())
}

错误处理

use cos_rust_sdk::CosError;

match object_client.get_object("nonexistent.txt").await {
    Ok(response) => println!("Success: {} bytes", response.data.len()),
    Err(CosError::Server { message, .. }) => {
        println!("Server error: {}", message);
    }
    Err(CosError::Http { message, .. }) => {
        println!("HTTP error: {}", message);
    }
    Err(e) => println!("Other error: {}", e),
}

完整示例

use cos_rust_sdk::{
    Config, CosClient, ObjectClient, BucketClient,
    BucketAcl, ListObjectsV2Options
};
use std::time::Duration;
use std::path::Path;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 配置
    let config = Config::new(
        "your-secret-id",
        "your-secret-key",
        "ap-beijing",
        "your-bucket-1234567890"
    ).with_timeout(Duration::from_secs(30));

    // 创建客户端
    let cos_client = CosClient::new(config)?;
    let object_client = ObjectClient::new(cos_client.clone());
    let bucket_client = BucketClient::new(cos_client);

    // 检查存储桶
    if !bucket_client.bucket_exists().await? {
        println!("Bucket does not exist");
        return Ok(());
    }

    // 上传文件
    let content = b"Hello, Tencent COS!";
    let upload_response = object_client
        .put_object("hello.txt", content.to_vec(), Some("text/plain"))
        .await?;
    println!("Uploaded with ETag: {}", upload_response.etag);

    // 列出对象
    let list_response = bucket_client
        .list_objects_v2(Some(ListObjectsV2Options {
            max_keys: Some(10),
            ..Default::default()
        }))
        .await?;
    
    println!("Objects in bucket:");
    for object in list_response.contents {
        println!("  {}: {} bytes", object.key, object.size);
    }

    // 下载文件
    let download_response = object_client.get_object("hello.txt").await?;
    println!("Downloaded: {}", String::from_utf8_lossy(&download_response.data));

    // 删除文件
    object_client.delete_object("hello.txt").await?;
    println!("File deleted");

    Ok(())
}

许可证

MIT License

贡献

欢迎提交 Issue 和 Pull Request!

媒体文件处理

批量上传图片

use cos_rust_sdk::{Config, CosClient, ObjectClient};
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = Config::new(secret_id, secret_key, region, bucket)
        .with_timeout(Duration::from_secs(120)); // 增加超时时间
    
    let cos_client = CosClient::new(config)?;
    let object_client = ObjectClient::new(cos_client);
    
    // 批量上传图片
    let images = vec![
        ("photos/image1.jpg", image1_data),
        ("photos/image2.png", image2_data),
        ("photos/image3.webp", image3_data),
    ];
    
    for (key, data) in images {
        object_client.put_object(key, data, None).await?;
        println!("上传成功: {}", key);
    }
    
    Ok(())
}

下载并保存图片

// 下载图片到本地
let local_path = "./downloaded_image.jpg";
object_client.get_object_to_file("photos/image1.jpg", local_path).await?;
println!("图片已保存到: {}", local_path);

支持的文件格式

SDK 支持自动检测以下文件格式的 MIME 类型:

  • 图片格式:JPEG, PNG, GIF, WebP, BMP, TIFF, SVG, ICO, HEIC, HEIF, AVIF, JXL
  • 视频格式:MP4, AVI, MOV, WMV, FLV, WebM, MKV, M4V, 3GP, 3G2, TS, MTS, M2TS, OGV
  • 音频格式:MP3, WAV, FLAC, AAC, OGG, WMA, M4A, Opus
  • 文档格式:PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, RTF
  • 压缩格式:ZIP, RAR, 7Z, TAR, GZ, BZ2
  • 文本格式:TXT, HTML, CSS, JS, JSON, XML, CSV, Markdown

详细的媒体文件处理指南请参考:MEDIA_GUIDE.md

更多示例请查看:

运行示例:

# 媒体上传示例(使用模拟数据)
cargo run --example media_upload

# 真实文件上传示例
cargo run --example real_file_upload -- /path/to/your/file.jpg
cargo run --example real_file_upload -- ./image.png ./video.mp4

# 格式支持演示
cargo run --example format_support

# 快速开始
cargo run --example quick_start_media

相关链接

Dependencies

~10–23MB
~307K SLoC