cos-rust-sdk 0.1.2

腾讯云对象存储 COS Rust SDK
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
# 腾讯云 COS Rust SDK

[![Crates.io](https://img.shields.io/crates/v/cos-rust-sdk.svg)](https://crates.io/crates/cos-rust-sdk)
[![Documentation](https://docs.rs/cos-rust-sdk/badge.svg)](https://docs.rs/cos-rust-sdk)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

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

## 特性

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

## 安装

在 `Cargo.toml` 中添加依赖:

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

## 快速开始

### 基本配置

```rust
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(())
}
```

### 对象操作

#### 上传对象

```rust
// 上传字节数据
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?;
```

#### 下载对象

```rust
// 下载到内存
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?;
```

#### 删除对象

```rust
// 删除单个对象
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);
}
```

#### 获取对象元数据

```rust
// 获取对象元数据
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);
```

### 存储桶操作

```rust
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?;
```

## 配置选项

### 基本配置

```rust
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 临时凭证

### 基本用法

```rust
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 策略配置

#### 预定义策略方法

```rust
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);
```

#### 自定义策略

```rust
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 示例

```rust
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(())
}
```

## 错误处理

```rust
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),
}
```

## 完整示例

```rust
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!



## 媒体文件处理

### 批量上传图片

```rust
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(())
}
```

### 下载并保存图片

```rust
// 下载图片到本地
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](MEDIA_GUIDE.md)

更多示例请查看:
- [examples/media_upload.rs]examples/media_upload.rs - 媒体文件上传下载示例(使用模拟数据)
- [examples/real_file_upload.rs]examples/real_file_upload.rs - 真实文件上传示例(处理本地文件)
- [examples/format_support.rs]examples/format_support.rs - 多格式文件支持演示
- [examples/quick_start_media.rs]examples/quick_start_media.rs - 快速开始媒体处理

运行示例:
```bash
# 媒体上传示例(使用模拟数据)
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
```

## 相关链接

- [腾讯云 COS 官方文档]https://cloud.tencent.com/document/product/436
- [腾讯云 COS API 文档]https://cloud.tencent.com/document/product/436/7751