Rust谷歌云存储库tame-gcs的使用,tame-gcs提供高效的GCS对象存储操作和API集成
Rust谷歌云存储库tame-gcs的使用,tame-gcs提供高效的GCS对象存储操作和API集成
tame-gcs
是一个遵循sans-io方法的Rust库,提供有限的Google Cloud Storage(GCS)操作功能。
特点
优点:
- 允许你完全控制如何向GCS发起HTTP请求
- 可以更灵活地管理依赖关系,不受特定版本HTTP相关库的限制
缺点:
- 仅支持部分GCS操作
- 相比其他功能更全面的GCS库需要更多样板代码
示例使用
以下是使用tame-gcs进行GCS操作的完整示例:
use tame_gcs::{objects::Object, BucketName, ObjectName};
// 初始化GCS客户端
let client = tame_gcs::Client::new();
// 创建存储桶名称和对象名称
let bucket_name = BucketName::new("my-bucket").unwrap();
let object_name = ObjectName::new("path/to/my/object").unwrap();
// 上传对象
let upload_request = Object::upload(
&client,
&bucket_name,
&object_name,
"text/plain",
b"Hello GCS!".to_vec(),
None,
)?;
// 获取对象
let get_request = Object::get(
&client,
&bucket_name,
&object_name,
None,
)?;
// 删除对象
let delete_request = Object::delete(
&client,
&bucket_name,
&object_name,
None,
)?;
完整示例demo
以下是一个更完整的示例,展示如何使用tame-gcs进行GCS操作:
use std::error::Error;
use tame_gcs::{objects::Object, BucketName, ObjectName};
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// 初始化GCS客户端
let client = tame_gcs::Client::new();
// 创建存储桶名称和对象名称
let bucket_name = BucketName::new("my-bucket")?;
let object_name = ObjectName::new("path/to/my/object")?;
// 上传对象
let upload_request = Object::upload(
&client,
&bucket_name,
&object_name,
"text/plain", // 内容类型
b"Hello GCS!".to_vec(), // 内容数据
None, // 可选元数据
)?;
println!("上传请求已创建");
// 获取对象
let get_request = Object::get(
&client,
&bucket_name,
&object_name,
None, // 可选参数
)?;
println!("获取请求已创建");
// 删除对象
let delete_request = Object::delete(
&client,
&bucket_name,
&object_name,
None, // 可选参数
)?;
println!("删除请求已创建");
Ok(())
}
安装
在项目中添加以下依赖到Cargo.toml:
tame-gcs = "0.14.0"
或运行:
cargo add tame-gcs
许可证
tame-gcs采用双重许可证:
- Apache License, Version 2.0
- MIT license
你可以选择其中任意一种许可证使用此库。
1 回复
Rust谷歌云存储库tame-gcs使用指南
tame-gcs
是一个Rust库,提供了高效操作Google Cloud Storage(GCS)的功能,支持对象存储操作和API集成。
主要特性
- 异步API设计
- 支持GCS对象的基本CRUD操作
- 支持分块上传大文件
- 支持签名URL生成
- 与tokio运行时良好集成
安装
在Cargo.toml中添加依赖:
[dependencies]
tame-gcs = "0.4"
tokio = { version = "1.0", features = ["full"] }
完整示例代码
use std::fs::File;
use std::io::Read;
use std::time::{Duration, SystemTime};
use tame_gcs::{
objects::{Object, ResumableUpload, ResumableUploadResponse},
signing::{SigningMethod, SignedUrlOptions},
types::{BucketName, ObjectName},
Client,
};
use tame_oauth::gcp::TokenProvider;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 初始化客户端
let tp = tame_oauth::gcp::TokenProviderWrapper::default();
let client = Client::new(tp);
// 测试用的bucket和object名称
let bucket = "test-bucket";
let object = "test-object.txt";
let test_content = b"Hello, GCS!";
let file_path = "large_file.dat"; // 假设的大文件路径
// 2. 上传对象
upload_object(&client, bucket, object, test_content).await?;
// 3. 下载对象
let downloaded = download_object(&client, bucket, object).await?;
println!("Downloaded content: {:?}", String::from_utf8_lossy(&downloaded));
// 4. 生成签名URL
let signed_url = generate_signed_url(&client, bucket, object).await?;
println!("Signed URL: {}", signed_url);
// 5. 分块上传大文件(演示用,实际需要真实文件路径)
// resumable_upload(&client, bucket, "large-file.dat", file_path).await?;
// 6. 删除对象
delete_object(&client, bucket, object).await?;
Ok(())
}
// 上传对象函数
async fn upload_object(
client: &Client,
bucket: &str,
object: &str,
content: &[u8],
) -> Result<(), Box<dyn std::error::Error>> {
let bucket = BucketName::try_from(bucket)?;
let object = ObjectName::try_from(object)?;
Object::upload(
&client,
content,
&bucket,
&object,
None,
None,
).await?;
println!("Uploaded {} to bucket {}", object, bucket);
Ok(())
}
// 下载对象函数
async fn download_object(
client: &Client,
bucket: &str,
object: &str,
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let bucket = BucketName::try_from(bucket)?;
let object = ObjectName::try_from(object)?;
let data = Object::download(&client, &bucket, &object, None).await?;
println!("Downloaded {} from bucket {}", object, bucket);
Ok(data)
}
// 删除对象函数
async fn delete_object(
client: &Client,
bucket: &str,
object: &str,
) -> Result<(), Box<dyn std::error::Error>> {
let bucket = BucketName::try_from(bucket)?;
let object = ObjectName::try_from(object)?;
Object::delete(&client, &bucket, &object, None).await?;
println!("Deleted {} from bucket {}", object, bucket);
Ok(())
}
// 生成签名URL函数
async fn generate_signed_url(
client: &Client,
bucket: &str,
object: &str,
) -> Result<String, Box<dyn std::error::Error>> {
let bucket = BucketName::try_from(bucket)?;
let object = ObjectName::try_from(object)?;
let expires = SystemTime::now() + Duration::from_secs(3600);
let opts = SignedUrlOptions::new(expires)
.with_method(SigningMethod::GET);
let url = Object::signed_url(&client, &bucket, &object, opts).await?;
println!("Generated signed URL for {}: {}", object, url);
Ok(url)
}
// 分块上传大文件函数
async fn resumable_upload(
client: &Client,
bucket: &str,
object: &str,
file_path: &str,
) -> Result<(), Box<dyn std::error::Error>> {
let bucket = BucketName::try_from(bucket)?;
let object = ObjectName::try_from(object)?;
let mut file = File::open(file_path)?;
let metadata = file.metadata()?;
let file_size = metadata.len() as usize;
// 初始化分块上传
let mut upload = ResumableUpload::new(&client, &bucket, &object, None, None)?;
// 设置文件大小
upload.set_size(file_size);
// 开始上传会话
let response = upload.start().await?;
match response {
ResumableUploadResponse::Completed(_) => {
println!("Upload completed in one request");
}
ResumableUploadResponse::InProgress(session) => {
println!("Resumable session started, uploading in chunks");
let mut buffer = vec![0; 1024 * 1024]; // 1MB chunks
let mut uploaded = 0;
loop {
let bytes_read = file.read(&mut buffer)?;
if bytes_read == 0 {
break;
}
let chunk = &buffer[..bytes_read];
let response = session.upload_chunk(chunk, uploaded).await?;
match response {
ResumableUploadResponse::Completed(_) => {
println!("Upload completed");
break;
}
ResumableUploadResponse::InProgress(new_session) => {
uploaded += bytes_read;
session = new_session;
}
}
}
}
}
Ok(())
}
错误处理示例
use tame_gcs::error::Error as GcsError;
async fn handle_errors() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new(tame_oauth::gcp::TokenProviderWrapper::default());
match download_object(&client, "my-bucket", "non-existent-file.txt").await {
Ok(data) => println!("Got data: {} bytes", data.len()),
Err(e) => {
if let Some(gcs_err) = e.downcast_ref::<GcsError>() {
match gcs_err {
GcsError::HttpError(status, _) if *status == 404 => {
println!("File not found");
}
_ => println!("GCS error: {}", gcs_err),
}
} else {
println!("Other error: {}", e);
}
}
}
Ok(())
}
注意事项
- 需要设置正确的Google Cloud权限
- 对于生产环境,建议使用服务账户凭证而不是默认凭证
- 大文件上传应考虑使用分块上传
- 异步操作需要使用tokio运行时
tame-gcs
提供了高效且符合Rust习惯的GCS操作接口,适合需要与Google Cloud Storage集成的Rust应用程序。