/* * Copyright (2024) Volcengine * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ use std::collections::HashMap; use std::env; use std::time::Duration; use chrono::Utc; use futures_core::Stream; use futures_util::{StreamExt, TryFutureExt}; use tokio::fs::File; use tokio::io::{AsyncRead, AsyncReadExt}; use tokio_util::io::ReaderStream; use ve_tos_rust_sdk::asynchronous::object::{GetObjectOutput, ObjectAPI, PutObjectFromBufferInput, PutObjectInput}; use ve_tos_rust_sdk::asynchronous::tos::{BufferStream, new_stream}; use ve_tos_rust_sdk::enumeration::ACLType::ACLPublicRead; use ve_tos_rust_sdk::enumeration::StorageClassType::StorageClassIa; use ve_tos_rust_sdk::object::{DeleteObjectInput, GetObjectInput, HeadObjectInput}; use crate::common::{base64_md5, gen_random_string}; use crate::common::asynchronous::{create_async_context, read_to_buf, read_to_string}; mod common; #[cfg(feature = "asynchronous")] #[test] fn test_main() { tokio_test::block_on(async { let context = create_async_context().await; let client = context.client(); let bucket = context.fixed_bucket(); let data = "hello world"; // 上传各种有效字符的对象 let keys = [" ", "a", "仅包含中文", "にほんご", "Ελληνικά", "Ελληνικά", "(!-_.*()/&$@=;:+ ,?\\{^}%`]>[~<#|'\")", "//"]; for k in keys { let o = client.put_object_from_buffer(&mut PutObjectFromBufferInput::new_with_content(bucket, k, data)).await.unwrap(); assert!(o.request_id().len() > 0); assert!(o.etag().len() > 0); assert_eq!(o.status_code(), 200); let mut o = client.get_object(&GetObjectInput::new(bucket, k)).await.unwrap(); assert!(o.request_id().len() > 0); assert!(o.etag().len() > 0); let buf = read_to_string(o.content().unwrap()).await; assert_eq!(buf, data); let o = client.delete_object(&DeleteObjectInput::new(bucket, k)).await.unwrap(); assert!(o.request_id().len() > 0); } let key = gen_random_string(10); let key = key.as_str(); let stream_data = new_stream(data); // 所有参数上传对象 let mut input = PutObjectInput::::new_with_content(bucket, key, stream_data); input.set_storage_class(StorageClassIa); input.set_acl(ACLPublicRead); input.set_content_disposition("attachment; filename=中文.txt"); let expires = Utc::now() + Duration::from_secs(3600); input.set_expires(expires); input.set_meta(HashMap::from([("aaa".to_string(), "bbb".to_string()), ("中文键".to_string(), "中文值".to_string())])); input.set_content_encoding("test-encoding"); input.set_content_language("test-language"); input.set_cache_control("test-cache-control"); input.set_content_type("text/plain"); input.set_website_redirect_location("http://test-website-redirection-location"); input.set_content_md5(base64_md5(data)); let o = client.put_object(&mut input).await.unwrap(); assert!(o.request_id().len() > 0); assert!(o.etag().len() > 0); assert_eq!(o.status_code(), 200); let mut o = client.get_object(&GetObjectInput::new(bucket, key)).await.unwrap(); assert!(o.request_id().len() > 0); assert!(o.etag().len() > 0); let buf = read_to_string(o.content().unwrap()).await; assert_eq!(buf, data); assert_eq!(o.content_length(), data.len() as i64); assert_eq!(o.storage_class().as_ref().unwrap(), &StorageClassIa); assert_eq!(o.expires().unwrap().format("%Y%m%dT%H%M%SZ").to_string(), expires.format("%Y%m%dT%H%M%SZ").to_string()); assert_eq!(o.content_disposition(), input.content_disposition()); assert_eq!(o.content_encoding(), input.content_encoding()); assert_eq!(o.content_language(), input.content_language()); assert_eq!(o.cache_control(), input.cache_control()); assert_eq!(o.content_type(), input.content_type()); assert_eq!(o.website_redirect_location(), input.website_redirect_location()); assert_eq!(o.meta().len(), 2); assert_eq!(o.meta().get("aaa").unwrap(), "bbb"); assert_eq!(o.meta().get("中文键").unwrap(), "中文值"); // 测试 head 接口 let o = client.head_object(&HeadObjectInput::new(bucket, key)).await.unwrap(); assert_eq!(o.content_length(), data.len() as i64); assert_eq!(o.storage_class().as_ref().unwrap(), &StorageClassIa); assert_eq!(o.expires().unwrap().format("%Y%m%dT%H%M%SZ").to_string(), expires.format("%Y%m%dT%H%M%SZ").to_string()); assert_eq!(o.content_disposition(), input.content_disposition()); assert_eq!(o.content_encoding(), input.content_encoding()); assert_eq!(o.content_language(), input.content_language()); assert_eq!(o.cache_control(), input.cache_control()); assert_eq!(o.content_type(), input.content_type()); assert_eq!(o.website_redirect_location(), input.website_redirect_location()); assert_eq!(o.meta().len(), 2); assert_eq!(o.meta().get("aaa").unwrap(), "bbb"); assert_eq!(o.meta().get("中文键").unwrap(), "中文值"); // 测试流式上传 let o = client.get_object(&GetObjectInput::new(bucket, key)).await.unwrap(); assert!(o.request_id().len() > 0); assert!(o.etag().len() > 0); let key2 = gen_random_string(10); let key2 = key2.as_str(); let o = client.put_object(&mut PutObjectInput::::new_with_content(bucket, key2, o)).await.unwrap(); assert!(o.request_id().len() > 0); assert!(o.etag().len() > 0); let mut o = client.get_object(&GetObjectInput::new(bucket, key2)).await.unwrap(); assert!(o.request_id().len() > 0); assert!(o.etag().len() > 0); assert_eq!(o.content_length(), data.len() as i64); let buf = read_to_string(o.content().unwrap()).await; assert_eq!(buf, data); // 上传大小为 0 的对象 let o = client.put_object(&mut PutObjectInput::::new_with_content(bucket, key2, new_stream(""))).await.unwrap(); assert!(o.request_id().len() > 0); assert!(o.etag().len() > 0); let o = client.get_object(&GetObjectInput::new(bucket, key2)).await.unwrap(); assert!(o.request_id().len() > 0); assert!(o.etag().len() > 0); assert_eq!(o.content_length(), 0); // 测试自动设置 MIME 类型 let keys = ["test", "test.TXT", "test.xml", "test.jpg", "test.HTML", "test.json", "test.mp4"]; let keys_cts = ["binary/octet-stream", "text/plain", "application/xml", "image/jpeg", "text/html", "application/json", "video/mp4"]; let cts = ["text/plain", ""]; for ct in cts { let mut index = 0; for k in keys { let mut input = PutObjectFromBufferInput::new(bucket, k); input.set_content_type(ct); let o = client.put_object_from_buffer(&input).await.unwrap(); assert!(o.request_id().len() > 0); assert!(o.etag().len() > 0); } for k in keys { let o = client.get_object(&GetObjectInput::new(bucket, k)).await.unwrap(); assert!(o.request_id().len() > 0); assert!(o.etag().len() > 0); assert_eq!(o.content_length(), 0); if ct == "" { assert_eq!(o.content_type(), keys_cts[index]); } else { assert_eq!(o.content_type(), ct); } index += 1; } } // 测试上传本地文件 let file_path = env::current_dir().unwrap().display().to_string() + "/tests/1.jpg"; let file = File::open(file_path.as_str()).await.unwrap(); let stream_data = ReaderStream::new(file); let mut input = PutObjectInput::>::new_with_content(bucket, key, stream_data); let o = client.put_object(&mut input).await.unwrap(); assert!(o.request_id().len() > 0); let mut input = GetObjectInput::new(bucket, key); input.set_process("image/info"); let mut o = client.get_object(&input).await.unwrap(); assert!(o.request_id().len() > 0); let result = read_to_string(o.content().unwrap()).await; assert!(result.len() > 0); println!("{}", result); assert!(result.contains("FileSize")); assert!(result.contains("Format")); assert!(result.contains("ImageHeight")); assert!(result.contains("ImageWidth")); let source_md5 = base64_md5(read_to_buf(&mut ReaderStream::new(File::open(file_path).await.unwrap())).await); let mut o = client.get_object(&GetObjectInput::new(bucket, key)).await.unwrap(); assert!(o.request_id().len() > 0); let target_md5 = base64_md5(read_to_buf(o.content().unwrap()).await); assert_eq!(source_md5, target_md5); context.tear_down().await; }) }