gbserver/gb-file/src/lib.rs

144 lines
4.8 KiB
Rust
Raw Normal View History

2025-02-25 09:00:35 -03:00
use minio::s3::client::Client;
use minio::s3::args::{BucketExistsArgs, MakeBucketArgs, RemoveObjectArgs, GetObjectArgs, PutObjectArgs, ListObjectsArgs};
use minio::s3::creds::StaticProvider;
use minio::s3::error::Error as MinioError;
use minio::s3::types::{BaseUrl, Item};
2025-02-24 11:40:46 -03:00
use std::io::Cursor;
2025-02-25 09:00:35 -03:00
use std::path::Path;
2025-02-24 11:40:46 -03:00
pub struct FileManager {
client: Client,
bucket_name: String,
}
impl FileManager {
pub async fn new(endpoint: &str, access_key: &str, secret_key: &str, bucket_name: &str, use_ssl: bool) -> Result<Self, MinioError> {
2025-02-25 09:00:35 -03:00
// Create BaseUrl from endpoint
let base_url = BaseUrl::from_string(endpoint)?;
let static_provider = StaticProvider::new(
access_key,
secret_key,
None,
);
let client = Client::new(base_url.clone(), Some(Box::new(static_provider)), None, None).unwrap();
2025-02-24 11:40:46 -03:00
Ok(Self {
client,
bucket_name: bucket_name.to_string(),
})
}
pub async fn ensure_bucket_exists(&self) -> Result<(), MinioError> {
let exists = self.client
2025-02-25 09:00:35 -03:00
.bucket_exists(&BucketExistsArgs::new(&self.bucket_name)?)
2025-02-24 11:40:46 -03:00
.await?;
if !exists {
self.client
2025-02-25 09:00:35 -03:00
.make_bucket(&MakeBucketArgs::new(&self.bucket_name)?)
2025-02-24 11:40:46 -03:00
.await?;
}
Ok(())
}
pub async fn upload_file(&self, path: &str, file_data: Vec<u8>) -> Result<(), MinioError> {
2025-02-25 09:00:35 -03:00
let reader = Cursor::new(&file_data);
let file_size = file_data.len() as u64;
let args = PutObjectArgs::new(
&self.bucket_name,
path,
reader,
Some(file_size),
None
)?;
2025-02-24 11:40:46 -03:00
self.client.put_object(&args).await?;
Ok(())
}
pub async fn download_file(&self, path: &str) -> Result<Vec<u8>, MinioError> {
2025-02-25 09:00:35 -03:00
let args = GetObjectArgs::new(&self.bucket_name, path)?;
2025-02-24 11:40:46 -03:00
let object = self.client.get_object(&args).await?;
let data = object.bytes().await?;
Ok(data.to_vec())
}
pub async fn copy_file(&self, source_path: &str, destination_path: &str) -> Result<(), MinioError> {
2025-02-25 09:00:35 -03:00
// Download the source file
let data = self.download_file(source_path).await?;
// Upload it to the destination
let reader = Cursor::new(&data);
let file_size = data.len() as u64;
let args = PutObjectArgs::new(
&self.bucket_name,
destination_path,
reader,
Some(file_size),
None
)?;
self.client.put_object(&args).await?;
2025-02-24 11:40:46 -03:00
Ok(())
}
pub async fn move_file(&self, source_path: &str, destination_path: &str) -> Result<(), MinioError> {
self.copy_file(source_path, destination_path).await?;
self.delete_file(source_path).await?;
Ok(())
}
pub async fn delete_file(&self, path: &str) -> Result<(), MinioError> {
2025-02-25 09:00:35 -03:00
let args = RemoveObjectArgs::new(&self.bucket_name, path)?;
2025-02-24 11:40:46 -03:00
self.client.remove_object(&args).await?;
Ok(())
}
pub async fn list_files(&self, prefix: &str) -> Result<Vec<String>, MinioError> {
2025-02-25 09:00:35 -03:00
// Create a predicate function that always returns true
let predicate = |_: Vec<Item>| -> bool { true };
let args = ListObjectsArgs::new(&self.bucket_name, &predicate)?;
2025-02-24 11:40:46 -03:00
let objects = self.client.list_objects(&args).await?;
2025-02-25 09:00:35 -03:00
// Filter objects based on prefix manually
let file_names: Vec<String> = objects
.into_iter()
.filter(|obj| obj.name().starts_with(prefix))
.map(|obj| obj.name().to_string())
.collect();
2025-02-24 11:40:46 -03:00
Ok(file_names)
}
pub async fn get_file_contents(&self, path: &str) -> Result<String, MinioError> {
let data = self.download_file(path).await?;
2025-02-25 09:00:35 -03:00
let contents = String::from_utf8(data)
.map_err(|_| MinioError::InvalidResponse(400, "Invalid UTF-8 sequence".to_string()))?;
2025-02-24 11:40:46 -03:00
Ok(contents)
}
pub async fn create_folder(&self, path: &str) -> Result<(), MinioError> {
let folder_path = if path.ends_with('/') {
path.to_string()
} else {
format!("{}/", path)
};
2025-02-25 09:00:35 -03:00
// Create empty file with folder path
2025-02-24 11:40:46 -03:00
self.upload_file(&folder_path, vec![]).await
}
pub async fn share_folder(&self, path: &str) -> Result<String, MinioError> {
2025-02-25 09:00:35 -03:00
// This is just a placeholder implementation
2025-02-24 11:40:46 -03:00
Ok(format!("Folder shared: {}", path))
}
pub async fn search_files(&self, prefix: &str, query: &str) -> Result<Vec<String>, MinioError> {
let files = self.list_files(prefix).await?;
let results = files.into_iter().filter(|f| f.contains(query)).collect();
Ok(results)
}
}