文盘Rust —— rust连接oss | 京东云技术团队
作者:京东科技 贾世闻
对象存储是云的基础组件之一,各大云厂商都有相关产品。这里跟大家介绍一下rust与对象存储交到的基本套路和其中的一些技巧。
基本连接
我们以 [S3 sdk](
https://github.com/awslabs/aws-sdk-rust)为例来说说基本的连接与操作,作者验证过aws、京东云、阿里云。主要的增删改查功能没有什么差别。
- 建立客户端
let shared_config = SdkConfig::builder() .credentials_provider(SharedCredentialsProvider::new(Credentials::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::config::Builder::from(&shared_config); let client = aws_sdk_s3::Client::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::DateTime::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::path::Path::new("/tmp/key") if let Some(p) = path.parent() { std::fs::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::File::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流式读取对象字节,分段写入文件。
对象存储的相关话题今天先聊到这儿,下期见。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
从原理到应用,人人都懂的ChatGPT指南 | 京东云技术团队
作者:京东科技 何雨航 引言 如何充分发挥ChatGPT潜能,已是众多企业关注的焦点。但是,这种变化对员工来说未必是好事情。IBM计划用AI替代7800个工作岗位,游戏公司使用MidJourney削减原画师人数......此类新闻屡见不鲜。理解并应用这项新技术,对于职场人来说重要性与日俱增。 一、GPT模型原理 理解原理是有效应用的第一步。ChatGPT是基于GPT模型的AI聊天产品,后文均简称为GPT。 从技术上看,GPT是一种基于Transformer架构的大语言模型(LLM)。GPT这个名字,实际上是"Generative Pre-trained Transformer"的缩写,中文意为“生成式预训练变换器”。 1.大模型和传统AI的区别是什么? 传统AI模型针对特定目标训练,因此只能处理特定问题。例如,很会下棋的AlphaGO。 而自然语言处理(NLP)试图更进一步,解决用户更为通用的问题。可以分为两个关键步骤:自然语言理解(NLU)和自然语言生成(NLG)。 以SIRI为代表的人工智能助手统一了NLU层,用一个模型理解用户的需求,然后将需求分配给特定的AI模型进行处理,实现N...
- 下一篇
万字长文详解如何使用Swift提高代码质量 | 京东云技术团队
前言 京喜APP最早在2019年引入了Swift,使用Swift完成了第一个订单模块的开发。之后一年多我们持续在团队/公司内部推广和普及Swift,目前Swift已经支撑了70%+以上的业务。通过使用Swift提高了团队内同学的开发效率,同时也带来了质量的提升,目前来自Swift的Crash的占比不到1%。在这过程中不断的学习/实践,团队内的Code Review,也对如何使用Swift来提高代码质量有更深的理解。 Swift特性 在讨论如何使用Swift提高代码质量之前,我们先来看看Swift本身相比ObjC或其他编程语言有什么优势。Swift有三个重要的特性分别是富有表现力/安全性/快速,接下来我们分别从这三个特性简单介绍一下: 富有表现力 Swift提供更多的编程范式和特性支持,可以编写更少的代码,而且易于阅读和维护。 基础类型- 元组、Enum关联类型 方法-方法重载 protocol- 不限制只支持class、协议默认实现、类专属协议 泛型-protocol关联类型、where实现类型约束、泛型扩展 可选值- 可选值申明、可选链、隐式可选值 属性- let、lazy、计算属性...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 2048小游戏-低调大师作品
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS8编译安装MySQL8.0.19
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Red5直播服务器,属于Java语言的直播服务器