P1: AsyncS3Vfs implementation (Phase 3)
- AsyncS3Vfs: spawn_blocking wrapper over S3Vfs - AsyncS3File: tokio::sync::Mutex for async state - Add Clone derive to S3Vfs - All backend methods wrapped with spawn_blocking Phase 3 complete: AsyncS3Vfs working Phase 4 pending: AsyncSmbVfs Phase 5 pending: WebDAV integration Tests: 293 passed, 0 failed
This commit is contained in:
@@ -8,6 +8,7 @@ use std::time::{Duration, SystemTime};
|
||||
use url::Url;
|
||||
|
||||
/// S3-compatible 文件系統後端
|
||||
#[derive(Clone)]
|
||||
pub struct S3Vfs {
|
||||
bucket: Bucket,
|
||||
credentials: Credentials,
|
||||
@@ -417,6 +418,28 @@ impl VfsBackend for S3Vfs {
|
||||
let to_key = Self::path_to_key(link);
|
||||
self.copy_object(&from_key, &to_key)
|
||||
}
|
||||
|
||||
fn copy(&self, from: &Path, to: &Path) -> Result<(), VfsError> {
|
||||
let from_key = Self::path_to_key(from);
|
||||
let to_key = Self::path_to_key(to);
|
||||
|
||||
// Check if source is a directory marker
|
||||
if from.ends_with("/") || from_key.ends_with('/') {
|
||||
// Directory copy: create destination directory marker
|
||||
let action = actions::PutObject::new(&self.bucket, Some(&self.credentials), &to_key);
|
||||
let url = action.sign(Duration::from_secs(3600));
|
||||
ureq::put(url.as_str())
|
||||
.send_bytes(&[])
|
||||
.map_err(|e| VfsError::Io(format!("S3 PutObject failed: {}", e)))?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Try HeadObject to verify source exists
|
||||
match self.head_object(&from_key) {
|
||||
Ok(_) => self.copy_object(&from_key, &to_key),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VfsFile for S3VfsFile {
|
||||
|
||||
Reference in New Issue
Block a user