feat(s3): Finally improve directory upload with proper path handling

- Added bucket parameter to upload_directory_recursive for explicit bucket specification
- Improved key construction logic to handle path prefixes more robustly
- Removed redundant trace logs and added more informative upload messages
- Fixed potential issue with bucket name extraction from prefix
- Ensured consistent path separator handling in S3 keys

The changes make the S3 upload functionality more reliable and maintainable by:
1. Explicitly passing bucket names instead of extracting from prefixes
2. Properly handling path separators in S3 keys
3. Providing clearer logging for upload operations
This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-10-30 12:52:21 -03:00
parent 5a6e36e6c2
commit 792186cf76

View file

@ -459,7 +459,7 @@ aws_sdk_s3::Client::from_conf(s3_config)
} }
} }
self.upload_directory_recursive(client, &path, &bucket) self.upload_directory_recursive(client, &path, &bucket, "/")
.await?; .await?;
info!("Uploaded template {} to Drive bucket {}", bot_name, bucket); info!("Uploaded template {} to Drive bucket {}", bot_name, bucket);
} }
@ -523,6 +523,7 @@ aws_sdk_s3::Client::from_conf(s3_config)
&'a self, &'a self,
client: &'a Client, client: &'a Client,
local_path: &'a Path, local_path: &'a Path,
bucket: &'a str,
prefix: &'a str, prefix: &'a str,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<()>> + 'a>> { ) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<()>> + 'a>> {
Box::pin(async move { Box::pin(async move {
@ -536,25 +537,26 @@ aws_sdk_s3::Client::from_conf(s3_config)
let entry = entry?; let entry = entry?;
let path = entry.path(); let path = entry.path();
let file_name = path.file_name().unwrap().to_string_lossy().to_string(); let file_name = path.file_name().unwrap().to_string_lossy().to_string();
let key = if prefix.is_empty() {
file_name.clone() // Construct key path, ensuring no duplicate slashes
} else { let mut key = prefix.trim_matches('/').to_string();
format!("{}/{}", prefix.trim_end_matches('/'), file_name) if !key.is_empty() {
}; key.push('/');
}
key.push_str(&file_name);
if path.is_file() { if path.is_file() {
info!("Uploading file: {} with key: {}", path.display(), key); info!("Uploading file: {} to bucket {} with key: {}",
path.display(), bucket, key);
let content = std::fs::read(&path)?; let content = std::fs::read(&path)?;
trace!("Writing file {} with key {}", path.display(), key);
client.put_object() client.put_object()
.bucket(prefix.split('/').next().unwrap_or("default.gbai")) .bucket(bucket)
.key(&key) .key(&key)
.body(content.into()) .body(content.into())
.send() .send()
.await?; .await?;
trace!("Successfully wrote file {}", path.display());
} else if path.is_dir() { } else if path.is_dir() {
self.upload_directory_recursive(client, &path, &key).await?; self.upload_directory_recursive(client, &path, bucket, &key).await?;
} }
} }
Ok(()) Ok(())