cloud-disk-sync 0.1.0

a cloud disk sync tool
Documentation
# WebDAV Provider 使用示例

本文档展示如何在实际项目中使用 WebDAV Provider。

## 快速开始

### 1. 添加 WebDAV 账户

```bash
# 使用 CLI 添加 WebDAV 账户
cloud-disk-sync add-account \
  --name my-webdav \
  --provider webdav

# 按提示输入:
# - WebDAV 服务器地址:https://dav.example.com
# - 用户名:your_username
# - 密码:your_password
```

### 2. 创建同步任务

```bash
# 创建从 WebDAV 到本地的同步任务
cloud-disk-sync create-task \
  --name "下载备份" \
  --source my-webdav:/remote/backup \
  --target local:/home/user/backup \
  --schedule "0 2 * * *"  # 每天凌晨2点
```

### 3. 执行同步

```bash
# 立即执行同步
cloud-disk-sync run --task <task_id>

# 预览同步(不实际执行)
cloud-disk-sync run --task <task_id> --dry-run
```

## 代码示例

### 基本使用

```rust
use cloud_disk_sync::config::{AccountConfig, ProviderType, RetryPolicy};
use cloud_disk_sync::providers::{WebDavProvider, StorageProvider};
use std::collections::HashMap;
use std::path::Path;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建配置
    let mut credentials = HashMap::new();
    credentials.insert("url".to_string(), "https://dav.example.com".to_string());
    credentials.insert("username".to_string(), "your_username".to_string());
    credentials.insert("password".to_string(), "your_password".to_string());

    let config = AccountConfig {
        id: "webdav-001".to_string(),
        provider: ProviderType::WebDAV,
        name: "My WebDAV".to_string(),
        credentials,
        rate_limit: None,
        retry_policy: RetryPolicy::default(),
    };

    // 创建 provider
    let provider = WebDavProvider::new(&config).await?;

    // 上传文件
    let local_file = Path::new("./document.pdf");
    let result = provider.upload(local_file, "/documents/document.pdf").await?;
    println!("上传成功: {} bytes", result.bytes_uploaded);

    // 下载文件
    let download_path = Path::new("./downloaded.pdf");
    provider.download("/documents/document.pdf", download_path).await?;
    println!("下载成功");

    // 列出目录
    let files = provider.list("/documents").await?;
    for file in files {
        println!("{} - {} bytes", file.path, file.size);
    }

    Ok(())
}
```

### 批量操作

```rust
use cloud_disk_sync::providers::{StorageProvider, WebDavProvider};
use std::path::PathBuf;

async fn batch_upload(
    provider: &WebDavProvider,
    files: Vec<PathBuf>,
    remote_dir: &str,
) -> Result<(), Box<dyn std::error::Error>> {
    for file in files {
        let file_name = file.file_name()
            .and_then(|n| n.to_str())
            .ok_or("Invalid filename")?;

        let remote_path = format!("{}/{}", remote_dir, file_name);

        match provider.upload(&file, &remote_path).await {
            Ok(result) => {
                println!("✓ {} - {} bytes", file_name, result.bytes_uploaded);
            }
            Err(e) => {
                eprintln!("✗ {} - 错误: {}", file_name, e);
            }
        }
    }

    Ok(())
}
```

### 目录同步

```rust
use cloud_disk_sync::providers::{WebDavProvider, StorageProvider};
use std::path::Path;
use walkdir::WalkDir;

async fn sync_directory(
    provider: &WebDavProvider,
    local_dir: &Path,
    remote_dir: &str,
) -> Result<(), Box<dyn std::error::Error>> {
    // 创建远程目录
    provider.mkdir(remote_dir).await?;

    // 遍历本地目录
    for entry in WalkDir::new(local_dir) {
        let entry = entry?;
        let path = entry.path();

        if path.is_file() {
            // 计算相对路径
            let relative = path.strip_prefix(local_dir)?;
            let remote_path = format!("{}/{}",
                                      remote_dir,
                                      relative.to_string_lossy()
            );

            // 上传文件
            provider.upload(path, &remote_path).await?;
            println!("已同步: {}", relative.display());
        }
    }

    Ok(())
}
```

### 错误处理

```rust
use cloud_disk_sync::providers::{WebDavProvider, StorageProvider};
use cloud_disk_sync::error::SyncError;

async fn safe_download(
    provider: &WebDavProvider,
    remote_path: &str,
    local_path: &std::path::Path,
) -> Result<(), Box<dyn std::error::Error>> {
    match provider.download(remote_path, local_path).await {
        Ok(result) => {
            println!("下载成功: {} bytes", result.bytes_downloaded);
            Ok(())
        }
        Err(SyncError::Provider(provider_err)) => {
            eprintln!("Provider 错误: {}", provider_err);
            Err(provider_err.into())
        }
        Err(SyncError::Network(net_err)) => {
            eprintln!("网络错误: {}", net_err);
            // 可以重试
            Err(net_err.into())
        }
        Err(e) => {
            eprintln!("未知错误: {}", e);
            Err(e.into())
        }
    }
}
```

### 并发操作

```rust
use cloud_disk_sync::providers::{WebDavProvider, StorageProvider};
use tokio::task::JoinSet;
use std::sync::Arc;

async fn concurrent_upload(
    provider: Arc<WebDavProvider>,
    files: Vec<(std::path::PathBuf, String)>,
) -> Result<(), Box<dyn std::error::Error>> {
    let mut tasks = JoinSet::new();

    for (local_path, remote_path) in files {
        let provider = provider.clone();

        tasks.spawn(async move {
            provider.upload(&local_path, &remote_path).await
        });
    }

    let mut success = 0;
    let mut failed = 0;

    while let Some(result) = tasks.join_next().await {
        match result? {
            Ok(_) => success += 1,
            Err(_) => failed += 1,
        }
    }

    println!("上传完成: {} 成功, {} 失败", success, failed);
    Ok(())
}
```

## 支持的 WebDAV 服务器

已测试兼容的 WebDAV 服务器:

- ✅ Nginx + ngx_http_dav_module
- ✅ Apache + mod_dav
- ✅ Nextcloud
- ✅ ownCloud
- ✅ SabreDAV
- ✅ Windows IIS WebDAV

## 最佳实践

### 1. 使用限流

```rust
use cloud_disk_sync::config::RateLimitConfig;

let rate_limit = Some(RateLimitConfig {
requests_per_minute: 60,
max_concurrent: 5,
chunk_size: 1024 * 1024, // 1MB
});
```

### 2. 配置重试策略

```rust
use cloud_disk_sync::config::RetryPolicy;

let retry_policy = RetryPolicy {
max_retries: 3,
initial_delay_ms: 1000,
max_delay_ms: 10000,
backoff_factor: 2.0,
};
```

### 3. 大文件处理

对于大文件,建议:

- 使用分块上传
- 启用进度回调
- 实现断点续传

### 4. 安全建议

- 使用 HTTPS 连接
- 定期更新密码
- 避免在代码中硬编码凭证
- 使用环境变量或配置文件

## 故障排除

### 连接超时

增加超时时间:

```rust
let client = Client::builder()
.timeout(Duration::from_secs(60))
.build() ?;
```

### 认证失败

检查:

1. 用户名和密码是否正确
2. WebDAV 服务器是否启用
3. URL 是否正确(注意尾部斜杠)

### 上传失败

可能原因:

1. 磁盘空间不足
2. 文件权限问题
3. 文件大小超过限制

## 更多信息

- [API 文档]https://docs.rs/cloud_disk_sync
- [问题反馈]https://github.com/your-repo/issues
- [测试说明]./tests/README.md