Rust WebDAV客户端库reqwest_dav的使用,支持高效文件传输和远程存储管理

Rust WebDAV客户端库reqwest_dav的使用,支持高效文件传输和远程存储管理

crates.io Documentation MIT/Apache-2 licensed CI

一个基于tokio和reqwest的异步WebDAV客户端库

特性

  • [x] 认证
    • [x] 基本认证
    • [x] 摘要认证
  • [x] 文件管理
    • [x] 获取文件
    • [x] 上传文件
    • [x] 移动文件
    • [x] 复制文件
    • [x] 删除文件
    • [x] 创建目录
    • [x] 列出文件

示例

use crate::{Auth, ClientBuilder, Depth, Error};

#[tokio::test]
async fn it_works() -> Result<(), Error> {
  
    // 创建客户端
    let client = ClientBuilder::new()
        .set_host("http://server/remote.php/dav/files/username/".to_string())
        .set_auth(Auth::Basic("username".to_owned(), "password".to_owned()))
        .build()?;

    // 列出文件
    println!(
        "{}",
        serde_json::to_string(&client.list("", Depth::Infinity).await?).unwrap()
    );
  
    // 删除文件
    client.delete("1.txt").await.unwrap();

    Ok(())
}

完整示例代码

以下是一个完整的WebDAV客户端使用示例,展示了文件上传、下载、列出和删除等操作:

use reqwest_dav::{Auth, ClientBuilder, Depth, Error};
use tokio::fs::File;
use tokio::io::AsyncWriteExt;

#[tokio::main]
async fn main() -> Result<(), Error> {
    // 1. 创建WebDAV客户端
    let client = ClientBuilder::new()
        .set_host("http://your-webdav-server.com/dav/".to_string())
        .set_auth(Auth::Basic("username".to_owned(), "password".to_owned()))
        .build()?;

    // 2. 列出目录内容
    println!("Listing directory contents:");
    let files = client.list("", Depth::Infinity).await?;
    for file in files {
        println!("- {} ({})", file.path, file.size);
    }

    // 3. 上传文件
    println!("Uploading file...");
    let data = b"Hello, WebDAV!";
    client.put("test.txt", data.to_vec()).await?;

    // 4. 下载文件
    println!("Downloading file...");
    let content = client.get("test.txt").await?;
    let mut file = File::create("local_test.txt").await?;
    file.write_all(&content).await?;

    // 5. 移动文件
    println!("Moving file...");
    client.mv("test.txt", "renamed.txt").await?;

    // 6. 删除文件
    println!("Deleting file...");
    client.delete("renamed.txt").await?;

    // 7. 创建目录
    println!("Creating directory...");
    client.mkcol("new_folder").await?;

    Ok(())
}

安装

在项目目录中运行以下Cargo命令:

cargo add reqwest_dav

或者在Cargo.toml中添加以下行:

reqwest_dav = "0.2.1"

许可证

MIT OR Apache-2.0


1 回复

Rust WebDAV客户端库reqwest_dav使用指南

reqwest_dav是一个基于reqwest的Rust WebDAV客户端库,提供了高效的文件传输和远程存储管理功能。

主要特性

  • 支持WebDAV协议的基本操作(PROPFIND, GET, PUT等)
  • 基于async/await的异步API
  • 支持大文件分块传输
  • 提供文件和目录管理功能
  • 支持认证(基本认证和摘要认证)

使用方法

添加依赖

首先在Cargo.toml中添加依赖:

[dependencies]
reqwest_dav = "0.3"
tokio = { version = "1.0", features = ["full"] }

基本示例

use reqwest_dav::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建客户端实例
    let client = Client::new("https://webdav.example.com")
        .with_credentials("username", "password");
    
    // 列出目录内容
    let files = client.list("/").await?;
    println!("Root directory contents: {:?}", files);
    
    // 上传文件
    let data = b"Hello, WebDAV!";
    client.put("/test.txt", data).await?;
    
    // 下载文件
    let content = client.get("/test.txt").await?;
    println!("File content: {:?}", String::from_utf8(content)?);
    
    // 创建目录
    client.mkdir("/new_folder").await?;
    
    // 删除文件
    client.delete("/test.txt").await?;
    
    Ok(())
}

高级功能

大文件分块上传

use reqwest_dav::Client;
use tokio::fs::File;
use tokio::io::AsyncReadExt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("https://webdav.example.com")
        .with_credentials("user", "pass");
    
    let mut file = File::open("large_file.zip").await?;
    let mut buffer = Vec::new();
    file.read_to_end(&mut buffer).await?;
    
    // 使用分块上传
    client.put_chunked("/uploads/large_file.zip", &buffer).await?;
    
    Ok(())
}

递归列出目录

use reqwest_dav::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("https://webdav.example.com");
    
    // 递归列出目录下所有文件和子目录
    let all_files = client.list_recursive("/documents").await?;
    println!("Found {} items", all_files.len());
    
    Ok(())
}

检查文件/目录是否存在

use reqwest_dav::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("https://webdav.example.com");
    
    if client.exists("/important_file.txt").await? {
        println!("File exists!");
    } else {
        println!("File not found");
    }
    
    Ok(())
}

错误处理

use reqwest_dav::Client;
use reqwest_dav::Error as DavError;

#[tokio::main]
async fn main() {
    let client = Client::new("https://webdav.example.com");
    
    match client.get("/nonexistent.txt").await {
        Ok(content) => println!("Got file content"),
        Err(DavError::NotFound) => eprintln!("File not found"),
        Err(DavError::PermissionDenied) => eprintln!("Permission denied"),
        Err(e) => eprintln!("Other error: {}", e),
    }
}

性能提示

  1. 重用Client实例,它内部维护了连接池
  2. 对大文件使用put_chunked方法
  3. 批量操作时考虑并行处理

完整示例

下面是一个综合使用reqwest_dav的完整示例,展示了多个功能的组合使用:

use reqwest_dav::Client;
use reqwest_dav::Error as DavError;
use tokio::fs::File;
use tokio::io::AsyncReadExt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 创建客户端并认证
    let client = Client::new("https://webdav.example.com")
        .with_credentials("user", "password");
    
    // 2. 检查工作目录是否存在,不存在则创建
    if !client.exists("/workdir").await? {
        client.mkdir("/workdir").await?;
        println!("Created work directory");
    }
    
    // 3. 上传本地文件
    let mut local_file = File::open("local_data.txt").await?;
    let mut buffer = Vec::new();
    local_file.read_to_end(&mut buffer).await?;
    
    // 根据文件大小选择上传方式
    if buffer.len() > 1024 * 1024 { // 大于1MB使用分块上传
        client.put_chunked("/workdir/data.txt", &buffer).await?;
        println!("Uploaded large file using chunked transfer");
    } else {
        client.put("/workdir/data.txt", &buffer).await?;
        println!("Uploaded file");
    }
    
    // 4. 递归列出目录内容
    let items = client.list_recursive("/workdir").await?;
    println!("Directory contains {} items:", items.len());
    for item in items {
        println!("- {} ({})", item.path, if item.is_dir { "dir" } else { "file" });
    }
    
    // 5. 下载文件并显示内容
    match client.get("/workdir/data.txt").await {
        Ok(content) => {
            println!("File content: {}", String::from_utf8_lossy(&content));
        }
        Err(DavError::NotFound) => {
            eprintln!("File not found on server");
        }
        Err(e) => {
            eprintln!("Error downloading file: {}", e);
        }
    }
    
    // 6. 清理 - 删除上传的文件
    client.delete("/workdir/data.txt").await?;
    println!("Cleanup complete");
    
    Ok(())
}

这个完整示例展示了:

  1. 客户端创建和认证
  2. 目录检查与创建
  3. 智能文件上传(自动选择普通或分块上传)
  4. 递归目录列表
  5. 文件下载和错误处理
  6. 清理操作

使用reqwest_dav可以轻松实现与WebDAV服务器的交互,适合各种文件管理场景。

回到顶部