精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

文盤Rust -- rust連接oss

jf_wN0SrCdH ? 來源:Rust語言中文社區 ? 2023-05-12 16:18 ? 次閱讀

對象存儲是云的基礎組件之一,各大云廠商都有相關產品。這里跟大家介紹一下rust與對象存儲交到的基本套路和其中的一些技巧。

基本連接

我們以 [S3 sdk](https://github.com/awslabs/aws-sdk-rust)為例來說說基本的連接與操作,作者驗證過aws、京東云、阿里云。主要的增刪改查功能沒有什么差別。

基本依賴 Cargo.toml

  # oss
  aws-config = { git = "https://github.com/awslabs/aws-sdk-rust", branch = "main" }
  aws-sdk-s3 = { git = "https://github.com/awslabs/aws-sdk-rust", branch = "main" }
  aws-types = { git = "https://github.com/awslabs/aws-sdk-rust", branch = "main",  feature = ["hardcoded-credentials"] }
  aws-credential-types = { git = "https://github.com/awslabs/aws-sdk-rust", branch = "main" }
  aws-smithy-types = { git = "https://github.com/awslabs/aws-sdk-rust", branch = "main" }

建立客戶端

let shared_config = SdkConfig::builder()
         .credentials_provider(SharedCredentialsProvider::new(
            "LTAI5t7NPuPKsXm6UeSa1",
            "DGHuK03ESXQYqQ83buKMHs9NAwz",
             None,
             None,
             "Static",
         )))
         .endpoint_url("http://oss-cn-beijing.aliyuncs.com")
         .region(Region::new("oss-cn-beijing"))
         .build();
     let s3_config_builder = aws_sdk_s3::from(&shared_config);
     let client = aws_sdk_s3::from_conf(s3_config_builder.build());

建立Client所需要的參數主要有你需要訪問的oss的AK、SK,endpoint url 以及服務所在的區域。以上信息都可以在服務商的幫助文檔查詢到。

對象列表

let mut obj_list = client
     .list_objects_v2()
     .bucket(bucket)
     .max_keys(max_keys)
     .prefix(prefix_str)
     .continuation_token(token_str);


let list = obj_list.send().await.unwrap();
println!("{:?}",list.contents());
println!("{:?}",list.next_continuation_token());

使用list_objects_v2函數返回對象列表,相比list_objects函數,list_objects_v2可以通過continuation_token和max_keys控制返回列表的長度。list.contents()返回對象列表數組,list.next_continuation_token()返回繼續查詢的token。

上傳文件

let content = ByteStream::from("content in file".as_bytes());
 let exp = aws_smithy_types::from_secs(100);
let upload = client
    .put_object()
    .bucket("bucket")
    .key("/test/key")
    .expires(exp)
    .body(content);
upload.send().await.unwrap();

指定bucket及對象路徑,body接受ByteStream類型作為文件內容,最后設置過期時間expires,無過期時間時不指定該配置即可。

下載文件


	
let key = "/tmp/test/key".to_string();
let resp = client
    .get_object()
    .bucket("bucket")
    .key(&key)
    .send()
    .await.unwrap();
let data = resp.body.collect().await.unwrap();
let bytes = data.into_bytes();


let path = std::new("/tmp/key")
if let Some(p) = path.parent() {
    std::create_dir_all(p).unwrap();
}
let mut file = OpenOptions::new()
    .write(true)
    .truncate(true)
    .create(true)
    .open(path).unwrap();
let _ = file.write(&*bytes);
file.flush().unwrap();

通過get_object()函數獲取GetObjectOutput。返回值的body 就是文件內容,將 body 轉換為 bytes,最后打開文件寫入即可。

刪除文件


	
let mut keys = vec![];
let key1 = ObjectIdentifier::builder()
    .set_key(Some("/tmp/key1".to_string()))
    .build();
let key2 = ObjectIdentifier::builder()
    .set_key(Some("/tmp/key2".to_string()))
    .build()
keys.push(key1);
keys.push(key2)
client
    .delete_objects()
    .bucket(bucket)
    .delete(Delete::builder().set_objects(Some(keys)).build())
    .send()
    .await
    .unwrap();

delete_objects 批量刪除對象。首先構建keys vector,定義要刪除的對象,然后通過Delete::builder(),構建 Delete model。

大文件上傳


	
let mut file = fs::open("/tmp/file_name").unwrap();
let chunk_size = 1024*1024;
let mut part_number = 0;
let mut upload_parts: Vec = Vec::new();


//獲取上傳id
let multipart_upload_res: CreateMultipartUploadOutput = self
    .client
    .create_multipart_upload()
    .bucket("bucket")
    .key("/tmp/key")
    .send()
    .await.unwrap();
let upload_id = match multipart_upload_res.upload_id() {
    Some(id) => id,
    None => {
        return Err(anyhow!("upload id is None"));
    }
};


//分段上傳文件并記錄completer_part
loop {
    let mut buf = vec![0; chuck_size];
    let read_count = file.read(&mut buf)?;
    part_number += 1;


    if read_count == 0 {
        break;
    }


    let body = &buf[..read_count];
    let stream = ByteStream::from(body.to_vec());


    let upload_part_res = self
        .client
        .upload_part()
        .key(key)
        .bucket(bucket)
        .upload_id(upload_id)
        .body(stream)
        .part_number(part_number)
        .send()
        .await.unwrap();


    let completer_part = CompletedPart::builder()
        .e_tag(upload_part_res.e_tag.unwrap_or_default())
        .part_number(part_number)
        .build();


    upload_parts.push(completer_part);


    if read_count != chuck_size {
        break;
    }
}
// 完成上傳文件合并
let completed_multipart_upload: CompletedMultipartUpload =
    CompletedMultipartUpload::builder()
        .set_parts(Some(upload_parts))
        .build();


let _complete_multipart_upload_res = self
    .client
    .complete_multipart_upload()
    .bucket("bucket")
    .key(key)
    .multipart_upload(completed_multipart_upload)
    .upload_id(upload_id)
    .send()
    .await.unwrap();

有時候面對大文件,比如幾百兆甚至幾個G的文件,為了節約帶寬和內存,我才采取分段上傳的方案,然后在對象存儲的服務端做合并。基本流程是:指定bucket和key,獲取一個上傳id;按流讀取文件,分段上傳字節流,并記錄CompletedPart;通知服務器按照CompletedPart 集合來合并文件。具體過程代碼已加注釋,這里不再累述。

大文件下載


	
let mut file = match OpenOptions::new()
            .truncate(true)
            .create(true)
            .write(true)
            .open("/tmp/target_file");
let key = "/tmp/test/key".to_string();
let resp = client
    .get_object()
    .bucket("bucket")
    .key(&key)
    .send()
    .await.unwrap();


let content_len = resp.content_length();
let mut byte_stream_async_reader = resp.body.into_async_read();
let mut content_len_usize: usize = content_len.try_into().unwrap();
loop {
    if content_len_usize > chunk_size {
        let mut buffer = vec![0; chunk_size];
        let _ = byte_stream_async_reader.read_exact(&mut buffer).await.unwrap();
        file.write_all(&buffer).unwrap();
        content_len_usize -= chunk_size;
        continue;
    } else {
        let mut buffer = vec![0; content_len_usize];
        let _ = byte_stream_async_reader.read_exact(&mut buffer).await.unwrap();
        file.write_all(&buffer).unwrap();
        break;
    }
}
file.flush().unwrap();

在從對象存儲服務端下載文件的過程中也會遇到大文件問題。為了節約帶寬和內存,我們采取讀取字節流的方式分段寫入文件。首先get_object()函數獲取ByteStream,通過async_reader流式讀取對象字節,分段寫入文件。

審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 對象存儲
    +關注

    關注

    0

    文章

    65

    瀏覽量

    11943
  • 存儲服務
    +關注

    關注

    0

    文章

    20

    瀏覽量

    5922
  • Rust
    +關注

    關注

    1

    文章

    226

    瀏覽量

    6497

原文標題:文盤Rust -- rust連接oss

文章出處:【微信號:Rust語言中文社區,微信公眾號:Rust語言中文社區】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    如何使用Rust連接Redis

    Redis是一款快速、開源、鍵值存儲數據庫,被廣泛應用于緩存、發布/訂閱系統、定時任務等場景中。Rust提供了很多Redis的客戶端庫,本教程將會介紹如何使用Rust連接Redis,以及如何通過
    的頭像 發表于 09-19 16:22 ?1968次閱讀

    如何在Rust中使用Memcached

    Memcached協議的實現,使得開發者可以在Rust中使用Memcached。 基礎用法 創建連接 使用Rust語言Memcached需要先創建一個連接??梢允褂?memcached
    的頭像 發表于 09-19 16:30 ?1093次閱讀

    Rust GUI實踐之Rust-Qt模塊

    Rust-Qt 是 Rust 語言的一個 Qt 綁定庫,它允許 Rust 開發者使用 Qt 框架來創建跨平臺的圖形界面應用程序。Qt 是一個跨平臺的應用程序框架,它提供了一系列的工具和庫,可以幫助
    的頭像 發表于 09-30 16:43 ?1375次閱讀

    Rust語言如何與 InfluxDB 集成

    InfluxDB Rust 客戶端。可以在 Cargo.toml 文件中添加以下依賴項: [dependencies] influxdb = "0.14.0" 連接到 InfluxDB 我們需要
    的頭像 發表于 09-30 16:45 ?951次閱讀

    如何在Rust連接和使用MySQL數據庫

    如何在Rust連接和使用MySQL數據庫。 安裝 mysql 模塊 這里我們假設你已經安裝了Rust編程語言工具鏈,在本教程中,我們將使用 mysql crate來連接和使用MySQ
    的頭像 發表于 09-30 17:05 ?1403次閱讀

    只會用Python?教你在樹莓派上開始使用Rust

    結合起來,并在Raspberry Pi上安裝Rust。設置Raspberry Pi對于此項目,您將需要:Raspberry PiLED。220-1k歐姆電阻。面包板和接線。使用GPIO 18連接到LED
    發表于 05-20 08:00

    怎樣去使用Rust進行嵌入式編程呢

    使用Rust進行嵌入式編程Use Rust for embedded development篇首語:Rust的高性能、可靠性和生產力使其適合于嵌入式系統。在過去的幾年里,Rust在程序
    發表于 12-22 07:20

    RUST在嵌入式開發中的應用是什么

    Rust是一種編程語言,它使用戶能夠構建可靠、高效的軟件,尤其是用于嵌入式開發的軟件。它的特點是:高性能:Rust具有驚人的速度和高內存利用率??煽啃裕涸诰幾g過程中可以消除內存錯誤。生產效率:優秀
    發表于 12-24 08:34

    Rust代碼中加載靜態庫時,出現錯誤 ` rust-lld: error: undefined symbol: malloc `怎么解決?

    “ [i]malloc ”、“ [i]exit ”。我驗證了使用 ` [i]nm ` 命令。 問題是我打算使用 ffi 在 rust 中使用這個靜態庫。當我嘗試在我的 Rust 代碼中加載靜態庫
    發表于 06-09 08:44

    rust-analyzer Rust編譯器前端實現

    ./oschina_soft/rust-analyzer.zip
    發表于 05-19 09:23 ?2次下載
    <b class='flag-5'>rust</b>-analyzer <b class='flag-5'>Rust</b>編譯器前端實現

    rust-av基于rust的多媒體工具包

    ./oschina_soft/rust-av.zip
    發表于 06-01 11:39 ?1次下載
    <b class='flag-5'>rust</b>-av基于<b class='flag-5'>rust</b>的多媒體工具包

    Chromium正式開始支持Rust

    ? Chromium 正式開始支持 Rust 目前的支持只是第一階段,在C++代碼中使用Rust寫的第三方庫(編譯成.so)。估計明年Chromium的二進制發行文件中會包含rust寫的庫。更廣
    的頭像 發表于 01-14 10:04 ?855次閱讀

    Rust -- tokio綁定cpu實踐

    )。core_affinity_rs是一個用于管理CPU親和力的Rust crate。目前支持Linux、Mac OSX和Windows。官方宣稱支持多平臺,本人只做了linux 操作系統的測試。
    的頭像 發表于 06-11 15:32 ?478次閱讀
    <b class='flag-5'>文</b><b class='flag-5'>盤</b><b class='flag-5'>Rust</b> -- tokio綁定cpu實踐

    Rust的內部工作原理

    Rust到匯編:了解 Rust 的內部工作原理 非常好的Rust系列文章,通過生成的匯編代碼,讓你了解很多Rust內部的工作機制。例如文章有 Rus
    的頭像 發表于 06-14 10:34 ?664次閱讀
    <b class='flag-5'>Rust</b>的內部工作原理

    從Rustup出發看Rust編譯生態

    從Rustup出發看Rust編譯生態 1. Rust和LLVM的關系是怎樣的? 2. Rustup中targets是什么,為什么可以安裝多個? 3. Rust在windows上為什么需要安裝Visual studio?
    的頭像 發表于 01-02 11:00 ?396次閱讀