Project Icon

webdav-client

TypeScript实现的WebDAV客户端库 适用于Node.js和浏览器

webdav-client是一个TypeScript编写的WebDAV客户端库,支持Node.js和浏览器环境。它提供简洁API接口,便于与WebDAV服务交互,实现目录内容获取、文件统计和配额查询等功能。该库支持多种认证方式,针对不同平台优化,适合开发各类WebDAV应用。

WebDAV

一个用TypeScript编写的WebDAV客户端,适用于NodeJS和浏览器

构建状态 npm版本 每月下载量 总下载量 依赖项(通过libraries.io)

关于

WebDAV是一种广为人知、稳定且高度灵活的协议,用于通过API与远程文件系统进行交互。由于其广泛使用,许多文件托管服务如Nextcloud/ownCloudBoxYandex都将其作为主要接口的备选方案。

这个库提供了一个WebDAV客户端接口,使与支持WebDAV的服务交互变得简单。API返回promise并解析结果。它解析并准备目录内容请求以便于使用,同时还提供了获取文件统计信息和配额等方法。

这个库的目标不是严格遵循RFC或标准的WebDAV接口,而是提供一个易于使用的客户端API,用于在Node或浏览器中与大多数WebDAV服务进行交互。

支持的版本/环境

版本5正在积极开发中。版本4处于维护模式,将接收安全和稳定性相关的错误修复。早期版本已经废弃,不会再收到更新。

版本5将库升级为使用ESM(ECMAScript模块),因此你的环境必须符合以下格式之一才能使用这个库:

  • NodeJS项目,在package.json中设置"type": "module"(ESM模式)
  • 使用像Webpack这样能处理ESM的工具打包的Web项目
  • React-native项目(通过直接导入或使用自动react-native入口)

如果你还没准备好升级,可以考虑使用这个库的版本4。

请求

这个库使用@buttercup/fetch以跨平台的方式发起请求。如果存在,它会使用浏览器的原生fetch,否则使用polyfill。在Node和其他环境中,它使用node-fetch

v5之前的版本使用Axios发起请求。

Node支持

支持表:

库主版本Node JS范围
v514+
v410-18
v310-16
v26-14
v14-12

浏览器支持

从这个库的版本3开始支持浏览器环境。

如前所述,v5引入了ESM,这可能需要在为浏览器打包时进行额外配置。

尽管你可以选择自行转译这个库的默认入口点(NodeJS),但不建议这样做 - 请使用专门的web版本。

在版本4中,你必须为web版本使用不同的入口点,虽然在版本5中仍可以这样做,但你不再需要:

import { createClient } from "webdav/web";

// 或

import { createClient } from "webdav";

// 在支持的打包工具中两种方式都可以

版本3/4支持浏览器中的UMD风格模块,但在版本5中不再支持。版本5只提供一个可以导入到其他支持ESM的项目中的ESM兼容包。

**注意:**在浏览器中不支持流,所以createReadStreamcreateWriteStream只是存根。调用它们会抛出异常。

React-Native支持

自版本5.6.0起,React-Native得到了更好的支持,使用了专门为该平台构建的版本。导入应该是自动的,但可以通过直接从/react-native导入来强制使用:

import { createClient } from "webdav/react-native";

**注意:**由于某些原因,Metro构建系统无法正确解析这些入口,你可能需要为React Native自定义babel配置以正确导入这个库:

module.exports = {
    presets: ["module:metro-react-native-babel-preset"],
    plugins: [
        [
            "module-resolver",
            {
                alias: {
                    // 将webdav客户端入口指向react native构建:
                    webdav: "webdav/dist/react-native"
                },
                extensions: [".tsx", ".ts", ".js", ".jsx", ".json"]
            }
        ]
    ]
};

使用这个覆盖后,你可以简单地从webdav导入。

类型

这个库为Node构建导出了Typescript类型。所有类型也可以直接从模块中导入:

import { AuthType, createClient } from "webdav";

const client = createClient("https://some-server.org", {
    authType: AuthType.Digest,
    username: "user",
    password: "pass"
});

安装

使用npm简单地安装为依赖:

npm install webdav --save

使用

使用方法是通过调用工厂函数createClient创建一个客户端适配器实例:

const { createClient } = require("webdav");

const client = createClient(
    "https://webdav.example.com/marie123",
    {
        username: "marie",
        password: "myS3curePa$$w0rd"
    }
);

// 获取目录内容
const directoryItems = await client.getDirectoryContents("/");
// 输出一个类似这样的结构:
// [{
//     filename: "/my-file.txt",
//     basename: "my-file.txt",
//     lastmod: "Mon, 10 Oct 2018 23:24:11 GMT",
//     size: 371,
//     type: "file"
// }]

认证和连接

如果没有提供authType配置参数,WebDAV客户端会自动检测使用哪种认证方式,在AuthType.NoneAuthType.Password之间选择。对于AuthType.TokenAuthType.Digest,你必须明确指定。

设置authType将自动管理连接时的Authorization头。

如果你不确定远程服务器是需要digest还是password认证,可以将authType设置为AuthType.Auto

基本/无认证

如果服务器不需要认证,你可以不使用认证 - 只需在配置中避免传递usernamepassword的值。

要使用基本认证,只需在配置中传递usernamepassword

这个库还允许通过设置httpAgenthttpsAgent属性来覆盖内置的HTTP和HTTPS代理。这些应该是node的http.Agenthttps.Agent的实例。

OAuth令牌

要使用令牌进行认证,将令牌数据传递给token字段并指定authType

createClient(
    "https://address.com",
    {
        authType: AuthType.Token,
        token: {
            access_token: "2YotnFZFEjr1zCsicMWpAA",
            token_type: "example",
            expires_in: 3600,
            refresh_token: "tGzv3JOkF0XG5Qx2TlKWIA",
            example_parameter: "example_value"
        }
    }
);

你也可以自己提供HA1(详情见此)。这使你能够在用户登录时生成HA1并保存它,这样你就不需要保存密码本身。

createClient("https://address.com", {
    authType: AuthType.Digest,
    username: "someUser",
    password: "",
    ha1: "在此处填入您之前生成的ha1"
});

摘要认证

如果服务器需要基于摘要的认证,您可以通过 authType 配置参数启用此功能,并提供 usernamepassword

createClient(
    "https://address.com",
    {
        authType: AuthType.Digest,
        username: "someUser",
        password: "myS3curePa$$w0rd"
    }
);

客户端配置

createClient 方法接受一个 WebDAV 服务 URL 和一个配置选项参数。

可用的配置选项如下:

选项默认值描述
authTypenull要使用的认证类型。如果未提供,默认会根据是否提供了 usernamepassword 来尝试检测。
contactHref此 URL用于 LOCK 的联系 URL。
headers{}提供给所有请求的附加头部。这里提供的头部会被方法特定的头部覆盖,包括 Authorization
httpAgentHTTP 代理实例。仅在 Node 中可用。参见 http.Agent
httpsAgentHTTPS 代理实例。仅在 Node 中可用。参见 https.Agent
password用于认证的密码。
token用于认证的令牌对象。
username用于认证的用户名。
withCredentials请求的凭证包含设置。

客户端方法

WebDAVClient 接口类型包含了 WebDAV 客户端实例的所有方法和签名。

copyFile

将文件从一个位置复制到另一个位置。

await client.copyFile(
    "/images/test.jpg",
    "/public/img/test.jpg"
);
(filename: string, destination: string, options?: WebDAVMethodOptions) => Promise<void>
参数是否必需描述
filename源文件名。
destination目标文件名。
options方法选项

createDirectory

创建新目录。

await client.createDirectory("/data/system/storage");
(path: string, options?: CreateDirectoryOptions) => Promise<void>
参数是否必需描述
path要创建的路径。
options创建目录选项。
options.recursive如果目录不存在,则递归创建。

options 扩展自 方法选项

递归创建

递归目录创建在请求方面是昂贵的。会发出多个 stat 请求(总数等于已存在路径的深度加1)以检测路径的哪些部分已经存在,直到找到一个不存在的段 - 然后只请求 创建 方法。

例如,递归调用创建路径 /a/b/c/d/e,其中 /a/b 已经存在,将会导致 3stat 请求(针对 /a/a/b/a/b/c)和 3createDirectory 请求(针对 /a/b/c/a/b/c/d/a/b/c/d/e)。

createReadStream

同步创建远程文件的可读流。

注意,虽然流会立即返回,但连接和获取文件仍在后台异步执行。在流开始接收数据之前会有一些延迟。

client
    .createReadStream("/video.mp4")
    .pipe(fs.createWriteStream("~/video.mp4"));

如果您只想流式传输文件的一部分,可以在选项参数中指定 range

client
    .createReadStream(
        "/video.mp4", 
        { range: { start: 0, end: 1024 } }
    ).pipe(fs.createWriteStream("~/video.mp4"));
(filename: string, options?: CreateReadStreamOptions) => Stream.Readable
参数是否必需描述
callback用于触发请求响应的回调。
filename要流式传输的远程文件。
options读取流选项。
options.range流范围配置。
options.range.start流的起始字节位置。
options.range.end流的结束字节位置。

options 扩展自 方法选项

createWriteStream

创建针对远程文件的写入流。

注意,虽然流会立即返回,但连接和写入远程文件仍在后台异步执行。在流开始传输数据之前会有一些延迟。

fs
    .createReadStream("~/Music/song.mp3")
    .pipe(client.createWriteStream("/music/song.mp3"));
(filename: string, options?: CreateWriteStreamOptions, callback?: CreateWriteStreamCallback) => Stream.Writable
参数是否必需描述
filename要流式写入的远程文件。
options写入流选项。
options.overwrite如果远程文件已存在,是否覆盖。默认为 true
callback连接建立并开始流式传输后触发的回调。回调会收到请求的响应。

options 扩展自 方法选项

customRequest

可以通过调用 customRequest 向附加的主机发出自定义请求。自定义请求提供了客户端内部使用的样板认证和其他请求选项。

const resp: Response = await this.client.customRequest("/alrighty.jpg", {
    method: "PROPFIND",
    headers: {
        Accept: "text/plain",
        Depth: "0"
    }
});
const result: DAVResult = await parseXML(await resp.text());
const stat: FileStat = parseStat(result, "/alrighty.jpg", false);
(path: string, requestOptions: RequestOptionsCustom) => Promise<Response>
参数是否必需描述
path要发出自定义请求的路径。
requestOptions请求选项 - 必需的参数如 urlmethod 等 - 请参考 RequestOptionsCustom 类型定义。

请求选项参数 扩展 方法选项,因为诸如 headers 之类的内容已经可以指定。

deleteFile

删除远程文件。

await client.deleteFile("/tmp.dat");
(filename: string, options?: WebDAVMethodOptions) => Promise<void>
参数是否必需描述
filename要删除的文件。
options方法选项

exists

检查文件或目录是否存在。

if (await client.exists("/some/path") === false) {
    await client.createDirectory("/some/path");
}
(path: string, options?: WebDAVMethodOptions) => Promise<boolean>
参数是否必需描述
path要检查的远程路径。
options方法选项

getDirectoryContents

获取远程目录的内容。返回 项目统计 数组。

// 获取当前目录内容:
const contents = await client.getDirectoryContents("/");
// 获取所有内容:
const contents = await client.getDirectoryContents("/", { deep: true });

文件可以使用 glob 选项进行通配(使用 minimatch 处理)。使用通配模式时,建议获取 deep 内容:

const images = await client.getDirectoryContents("/", { deep: true, glob: "/**/*.{png,jpg,gif}" });
(path: string, options?: GetDirectoryContentsOptions) => Promise<Array<FileStat> | ResponseDataDetailed<Array<FileStat>>>
参数是否必需描述
path要获取内容的路径。
options配置选项。
options.deep获取深层结果(递归)。默认为 false
options.details获取详细结果(项目统计信息,头部)。默认为 false
options.glob用于匹配文件名的通配符字符串。默认不设置。

options 扩展自 方法选项

getFileContents

获取远程文件的内容。默认返回二进制内容(Buffer):

const buff: Buffer = await client.getFileContents("/package.zip");

如果传输的文件较大,建议使用流。

也可以获取文本文件:

const str: string = await client.getFileContents("/config.json", { format: "text" });
(filename: string, options?: GetFileContentsOptions) => Promise<BufferLike | string | ResponseDataDetailed<BufferLike | string>>
参数是否必需描述
filename要获取内容的文件。
options配置选项。
options.details获取详细结果(附加头部)。默认为 false
options.format是获取二进制("binary")数据还是文本("text")。默认为 "binary"。

options 扩展自 方法选项

getFileDownloadLink

生成可下载文件的公共链接。此方法是同步的。在 URL 中暴露身份验证详细信息

并非所有服务器都支持此功能。只有基本身份验证和未经身份验证的连接支持此方法。

const downloadLink: string = client.getFileDownloadLink("/image.png");
(filename: string) => string
参数是否必需描述
filename要生成下载链接的远程文件。

getFileUploadLink

生成文件上传的 URL。此方法是同步的。在 URL 中暴露身份验证详细信息

const uploadLink: string = client.getFileUploadLink("/image.png");
(filename: string) => string
参数是否必需描述
filename要生成上传链接的远程文件。

getQuota

获取当前账户的配额信息:

const quota: DiskQuota = await client.getQuota();
// {
//     "used": 1938743,
//     "available": "unlimited"
// }
(options?: GetQuotaOptions) => Promise<DiskQuota | null | ResponseDataDetailed<DiskQuota | null>>
参数是否必需描述
options配置选项。
options.details返回详细结果(头部等)。默认为 false
options.path用于发出配额请求的路径。

options 扩展自 方法选项

lock

锁定远程资源(使用写入锁)。

const lock = await client.lock("/file.doc");

// 稍后
await client.unlock("/file.doc", lock.token);
(path: string, options?: LockOptions) => Promise<LockResponse>
参数是否必需描述
path要锁定的路径。
options配置选项。
options.timeoutWebDAV 锁请求超时。参见 WebDAV Timeout 头部文档
options.refreshToken应刷新的先前有效锁定令牌。

options 扩展自 方法选项

moveFile

将文件移动到另一个位置。

await client.moveFile("/file1.png", "/file2.png");
(filename: string, destinationFilename: string, options?: WebDAVMethodOptions) => Promise<void>
参数是否必需描述
filename要移动的文件。
destinationFilename目标文件名。
options方法选项

putFileContents

将数据写入远程文件。当文件未写入时返回 false(例如 { overwrite: false } 且文件已存在),否则返回 true

// 写入缓冲区:
await client.putFileContents("/my/file.jpg", imageBuffer, { overwrite: false });
// 写入文本文件:
await client.putFileContents("/my/file.txt", str);
(filename: string, data: string | BufferLike | Stream.Readable, options?: PutFileContentsOptions) => Promise<boolean>
参数是否必需描述
filename要写入的文件。
data要写入的数据。可以是字符串、缓冲区或可读流。
options配置选项。
options.contentLength数据内容长度覆盖。可以是布尔值(true默认)= 计算,false = 不设置)或表示文件确切字节长度的数字。
options.overwrite如果远程文件存在,是否覆盖。默认为 true

options 扩展自 方法选项

partialUpdateFileContents

使用部分更新来更新远程文件。此方法适用于更新文件而无需下载和重新上传整个文件。

请注意,此方法未标准化,可能并非所有服务器都支持。 要使用此功能,必须满足以下条件之一:

(filePath: string, start: number, end: number, data: string | BufferLike | Stream.Readable, options?: WebDAVMethodOptions)=> Promise<void>
参数是否必需描述
filePath要更新的文件。
start起始字节位置。(包含)
end结束字节位置。(包含)
data要写入的数据。可以是字符串、缓冲区或可读流。
options配置选项。

search

根据 rfc5323 执行 WebDAV 搜索。

const searchRequest = `
<?xml version="1.0" encoding="UTF-8"?>
<d:searchrequest xmlns:d="DAV:" xmlns:f="http://example.com/foo">
    <f:natural-language-query>
    查找上周更改的文件
    </f:natural-language-query>
</d:searchrequest>
`
const result: SearchResult = await client.search("/some-collection", { data: searchRequest });
(path: string, options?: SearchOptions) => Promise<SearchResult | ResponseDataDetailed<SearchResult>>
参数是否必需描述
path执行搜索的远程路径。
options配置选项。
options.details返回详细结果(头部等)。默认为 false
options 继承自方法选项

stat

获取文件或目录的 stat 对象。返回一个项目统计信息

const stat: FileStat = await client.stat("/some/file.tar.gz");
(path: string, options?: StatOptions) => Promise<FileStat | ResponseDataDetailed<FileStat>>
参数是否必需描述
path要获取统计信息的远程路径。
options配置选项。
options.details返回详细结果(包括头部等)。默认为 false

options 继承自方法选项

unlock

使用令牌解锁被锁定的资源。

await client.unlock("/file.doc", lock.token);
(path: string, token:string, options?: WebDAVMethodOptions) => Promise<void>
参数是否必需描述
path要解锁的远程路径。
token之前锁定请求中获得的令牌字符串。
options配置选项。

options 继承自方法选项

自定义属性

对于像 stat 这样在底层使用 PROPFIND 方法的请求,可以为该方法提供自定义请求体,以便服务器可能响应额外或不同的数据。可以通过在方法选项中设置 data 属性来覆盖请求体。

方法选项

大多数 WebDAV 方法都继承自 WebDAVMethodOptions,它允许设置自定义头部等内容。

选项是否必需描述
data可选的请求体/数据值。这会覆盖原始请求体(如果适用)。
headers可选的头部对象,应用于请求。这些头部会覆盖所有其他头部,请谨慎使用。
signalAbortSignal 实例,用于中止请求。

常见数据结构

项目统计信息

项目统计信息是描述文件或目录的对象。它们类似于以下结构:

{
    "filename": "/test",
    "basename": "test",
    "lastmod": "Tue, 05 Apr 2016 14:39:18 GMT",
    "size": 0,
    "type": "directory",
    "etag": null
}

或:

{
    "filename": "/image.jpg",
    "basename": "image.jpg",
    "lastmod": "Sun, 13 Mar 2016 04:23:32 GMT",
    "size": 42497,
    "type": "file",
    "mime": "image/jpeg",
    "etag": "33a728c7f288ede1fecc90ac6a10e062"
}

属性:

属性名类型出现情况描述
filename字符串始终远程项目的文件路径
basename字符串始终远程项目的基本文件名,不包含路径
lastmod字符串始终项目的最后修改日期
size数字始终文件大小 - 目录为 0
type字符串始终项目类型 - "file" 或 "directory"
mime字符串仅文件MIME 类型 - 仅适用于文件项目
etag字符串 / null支持时文件的 ETag
props对象details: true包含服务器返回的所有项目属性的 Props 对象

详细响应

返回结果的请求,如 getDirectoryContentsgetFileContentsgetQuotasearchstat,可以配置为返回更详细的信息,例如响应头部。在它们的选项参数中传递 { details: true } 以接收如下对象:

属性类型描述
data*该过程返回的数据。类型与不使用 { details: true } 调用时返回的类型相同
headers对象响应头部。
status数字数字状态码。
statusText字符串状态文本。

CORS

CORS 是浏览器采用的一种安全执行技术,用于确保请求在预期的上下文中执行和接收。如果目标服务器在从浏览器发出请求时不返回 CORS 头部,它可能会与此库冲突。处理这个问题是你的责任。

众所周知,Nextcloud 服务器默认不返回友好的 CORS 头部,这使得在浏览器环境中使用此库变得不可能。当然,你可以强制添加 CORS 头部(Apache 或 Nginx 配置),但请自行承担风险。

使用此 WebDAV 客户端的项目

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号