diff --git a/src/config/mod.rs b/src/config/mod.rs index c16b89a6..57c50b0a 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -250,6 +250,8 @@ impl From for Config { secret, duration, bucket_use_path, + path, + directory_structure, } => { let path_style = if bucket_use_path { rusty_s3::UrlStyle::Path @@ -263,9 +265,11 @@ impl From for Config { let credentials = rusty_s3::Credentials::new(key, secret); MediaBackendConfig::S3 { - bucket: bucket, - credentials: credentials, + bucket, + credentials, duration: Duration::from_secs(duration), + path, + directory_structure, } } }, @@ -517,6 +521,9 @@ pub enum IncompleteMediaBackendConfig { duration: u64, #[serde(default = "false_fn")] bucket_use_path: bool, + path: Option, + #[serde(default)] + directory_structure: DirectoryStructure, }, } @@ -539,6 +546,8 @@ pub enum MediaBackendConfig { bucket: rusty_s3::Bucket, credentials: rusty_s3::Credentials, duration: Duration, + path: Option, + directory_structure: DirectoryStructure, }, } diff --git a/src/service/globals/mod.rs b/src/service/globals/mod.rs index 45def51a..8ed92cae 100644 --- a/src/service/globals/mod.rs +++ b/src/service/globals/mod.rs @@ -488,23 +488,40 @@ impl Service { directory_structure: &DirectoryStructure, sha256_hex: &str, ) -> Result { - let mut r = PathBuf::new(); - r.push(media_directory); + Ok(PathBuf::from_iter(self.split_media_path( + Some(media_directory), + directory_structure, + sha256_hex, + )?)) + } - if let DirectoryStructure::Deep { length, depth } = directory_structure { - let mut filename = sha256_hex; - for _ in 0..depth.get() { - let (current_path, next) = filename.split_at(length.get().into()); - filename = next; - r.push(current_path); + pub fn split_media_path<'a>( + &self, + media_directory: Option<&'a str>, + directory_structure: &DirectoryStructure, + sha256_hex: &'a str, + ) -> Result> { + match directory_structure { + DirectoryStructure::Flat => match media_directory { + Some(path) => Ok(vec![path, sha256_hex]), + None => Ok(vec![sha256_hex]), + }, + DirectoryStructure::Deep { length, depth } => { + let mut r: Vec<&'a str> = Vec::with_capacity((depth.get() + 2).into()); + if let Some(path) = media_directory { + r.push(path); + } + let mut filename = sha256_hex; + for _ in 0..depth.get() { + let (current_path, next) = filename.split_at(length.get().into()); + filename = next; + r.push(current_path); + } + r.push(filename); + + Ok(r) } - - r.push(filename); - } else { - r.push(sha256_hex); } - - Ok(r) } pub fn shutdown(&self) { diff --git a/src/service/media/mod.rs b/src/service/media/mod.rs index 36817562..71a7dd9f 100644 --- a/src/service/media/mod.rs +++ b/src/service/media/mod.rs @@ -621,10 +621,16 @@ impl Service { bucket, credentials, duration, + path, + directory_structure, } => { let sha256_hex = hex::encode(sha256_digest); + let file_name = services() + .globals + .split_media_path(path.as_deref(), directory_structure, &sha256_hex)? + .join("/"); let url = bucket - .get_object(Some(credentials), &sha256_hex) + .get_object(Some(credentials), &file_name) .sign(*duration); let client = services().globals.default_client(); @@ -680,9 +686,16 @@ pub async fn create_file(sha256_hex: &str, file: &[u8]) -> Result<()> { bucket, credentials, duration, + path, + directory_structure, } => { + let file_name = services() + .globals + .split_media_path(path.as_deref(), directory_structure, sha256_hex)? + .join("/"); + let url = bucket - .put_object(Some(credentials), sha256_hex) + .put_object(Some(credentials), &file_name) .sign(*duration); let client = services().globals.default_client(); @@ -767,9 +780,15 @@ async fn delete_file(sha256_hex: &str) -> Result<()> { bucket, credentials, duration, + path, + directory_structure, } => { + let file_name = services() + .globals + .split_media_path(path.as_deref(), directory_structure, sha256_hex)? + .join("/"); let url = bucket - .delete_object(Some(credentials), sha256_hex) + .delete_object(Some(credentials), &file_name) .sign(*duration); let client = services().globals.default_client();