WebDAV客户端,用Typescript编写,用于NodeJS和浏览器
https://github.com/kytrun/web...

关于

WebDAV是一种知名的、稳定的、高度灵活的协议,用于通过API与远程文件系统进行交互。由于它是如此广泛,许多文件托管服务,如Box, Nextcloud/ownCloud和Yandex使用它作为其主要接入接口之一。
这个库提供了一个WebDAV客户端接口,使与启用WebDAV的服务的交互变得容易。API返回promises并使用结果进行解析。它解析和准备目录内容请求,以方便使用,并提供获取文件统计数据和配额等内容的方法。
这个库的目的不是遵循RFC或严格遵守标准WebDAV接口,而是提供一个易于使用的客户端API,用于从Node或浏览器使用大多数WebDAV服务。

Node support

此库与NodeJS版本10及以上兼容(为了获得版本6/8的支持,请使用2.. js的版本。对于版本4支持,请使用范围为1.的版本)。版本2。X和1。X不再受支持,因此使用它们的风险由您自己承担。版本3。X已弃用,可能会收到奇数错误修复.

Browser support

WebDAV客户端在浏览器版本3中得到支持。编译设置指定了Internet Explorer 11支持的最低浏览器版本,但是不会定期在该浏览器中进行测试。
尽管您可以选择自己编译这个库的默认入口点(NodeJS),但不建议使用专用的web版本。
您可以通过不同的入口点使用web版本:

import { createClient } from "webdav/web";

浏览器版本使用UMD-style的模块定义,这意味着您可以使用<script>标记在浏览器中加载库。当使用此方法时,库在窗口对象上可用:window. webdav。例如:

const client = window.WebDAV.createClient(/* ... */);

注意:流在浏览器中是不可用的,所以createReadStream和createWriteStream只做保留。调用它们将引发异常。

Types

Typescript类型与这个库一起导出,用于Node构建。所有类型也可以直接从模块导入:

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"
    }
);

// Get directory contents
const directoryItems = await client.getDirectoryContents("/");
// Outputs a structure like:
// [{
//     filename: "/my-file.txt",
//     basename: "my-file.txt",
//     lastmod: "Mon, 10 Oct 2018 23:24:11 GMT",
//     size: 371,
//     type: "file"
// }]

Authentication & Connection

WebDAV客户端自动检测在AuthType.None和AuthType.Password之间使用哪种身份验证。如果没有authType提供配置参数。你必须显式指定AuthType.Token 还是 AuthType.Digest
设置authType将在连接时自动管理Authorization标头。

Basic/no authentication

如果服务器不需要身份验证,您可以使用客户端-只需避免在配置中传递任何值给用户名和密码。
要使用基本身份验证,只需在配置中传递用户名和密码。
这个库还允许通过设置相应的属性httpAgent和httpAgent来覆盖内置的HTTP和HTTPS代理。这些应该分别是http.Agent 和 https.Agent 的实例代理。

OAuth tokens

要使用令牌进行身份验证,将令牌数据传递到令牌字段并指定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"
        }
    }
);

Digest authentication

如果服务器需要基于摘要的身份验证,您可以通过authType配置参数启用此功能,以及提供用户名和密码:

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

Client configuration

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

选项默认值描述
authTypenull要使用的认证类型。如果没有提供,则默认尝试根据是否提供用户名和密码进行检测。
headers{}为所有请求提供额外的头信息。这里提供的头被特定于方法的头覆盖,包括Authorization。
httpAgentNoneHTTP代理实例。仅支持Node。看到http.Agent。
httpsAgentNoneHTTP代理实例。仅支持Node。看到http.Agent。
maxBodyLengthNone允许发送的最大体长(以字节为单位)。
maxContentLengthNone允许接收的最大内容长度,以字节为单位。
passwordNone鉴权密码。
tokenNone用于身份验证的令牌对象。
usernameNone鉴权用户名。
withCredentialsNoneAxios的凭据包含设置。

Client methods

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

copyFile

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

await client.copyFile(
    "/images/test.jpg",
    "/public/img/test.jpg"
);
(filename: string, destination: string, options?: WebDAVMethodOptions) => Promise<void>
KEY是否必填描述
filenameYesThe source filename.
destinationYesThe destination filename.
optionsNoMethod options.

createDirectory

创建一个新目录:

await client.createDirectory("/data/system/storage");
(path: string, options?: CreateDirectoryOptions) => Promise<void>
KEY是否必填描述
pathYesThe path to create.
optionsNoCreate directory options.
options.recursiveNo如果目录不存在,递归地创建目录。

Options扩展了方法选项

递归创建

递归目录创建在请求方面开销很大。进行多个统计请求(现有路径的深度总和+1),以检测路径的哪些部分已经存在,直到找到一个不存在的段—然后只请求创建方法。
例如,递归调用创建路径/a/b/c/d/e,其中/a/b已经存在,将导致3个stat请求(/a, /a/b/ b和/a/b/c)和3个createDirectory请求(/a/b/c, /a/b/c/d和/a/b/c/d/e)。

创建可读流

同步地为远程文件创建可读流。
注意,尽管流立即返回,但文件的连接和获取仍然在后台异步执行。在流开始接收数据之前会有一些延迟。

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
KEY是否必填描述
callbackNo用请求的响应触发的回调。
filenameYesThe remote file to stream.
optionsNoRead stream options.
options.rangeNo流范围配置。
options.range.startYesByte-position for the start of the stream.
options.range.endNoByte-position for the end of the stream.

Options扩展了方法选项

创建写入流

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

fs
    .createReadStream("~/Music/song.mp3")
    .pipe(client.createWriteStream("/music/song.mp3"));
(filename: string, options?: CreateWriteStreamOptions, callback?: CreateWriteStreamCallback) => Stream.Writable
KEY是否必填描述
filenameYesThe remote file to stream.
optionsNoWrite stream options.
options.overwriteNo如果远程文件已经存在,是否覆盖该文件。默认为true。
callbackNo回调函数,在建立连接并启动流时触发。Callback与请求的响应一起调用。

Options扩展了方法选项

customRequest

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

const resp: Response = await this.client.customRequest("/alrighty.jpg", {
    method: "PROPFIND",
    headers: {
        Accept: "text/plain",
        Depth: "0"
    },
    responseType: "text"
});
const result: DAVResult = await parseXML(resp.data);
const stat: FileStat = parseStat(result, "/alrighty.jpg", false);
(path: string, requestOptions: RequestOptionsCustom) => Promise<Response>
KEY是否必填描述
pathYesThe path to make a custom request against.
requestOptionsYes请求选项-所需的参数,如url,方法等-参考RequestOptionsCustom类型定义。

request options参数不会扩展方法选项,因为像头这样的东西已经可以指定了。

删除文件

await client.deleteFile("/tmp.dat");`
(filename: string, options?: WebDAVMethodOptions) => Promise<void>
KEY是否必填描述
filenameYesThe file to delete.
optionsNoMethod options.

检查目录或文件是否存在

if (await client.exists("/some/path") === false) {
    await client.createDirectory("/some/path");
}
(path: string, options?: WebDAVMethodOptions) => Promise<boolean>
KEY是否必填描述
pathYesThe remote path to check.
optionsNoMethod options.

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

// Get current directory contents:
const contents = await client.getDirectoryContents("/");
// Get all contents:
const contents = await client.getDirectoryContents("/", { deep: true });

Files can be globbed using the glob option (processed using minimatch). When using a glob pattern it is recommended to fetch deep contents:

const images = await client.getDirectoryContents("/", { deep: true, glob: "/**/*.{png,jpg,gif}" });
(path: string, options?: GetDirectoryContentsOptions) => Promise<Array<FileStat> | ResponseDataDetailed<Array<FileStat>>>
KEY是否必填描述
pathYesThe path to fetch the contents of.
optionsNoConfiguration options.
options.deepNoFetch deep results (recursive). Defaults to false.
options.detailsNoFetch detailed results (item stats, headers). Defaults to false.
options.globNoGlob string for matching filenames. Not set by default.

Options扩展了方法选项

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

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

如果传输的文件比较大,建议使用流。
文本文件也可以获取:

const str: string = await client.getFileContents("/config.json", { format: "text" });

指定maxContentLength选项来改变客户端在请求中可以接收的最大字节数(仅限NodeJS)。

(filename: string, options?: GetFileContentsOptions) => Promise<BufferLike | string | ResponseDataDetailed<BufferLike | string>>
KEY是否必填描述
filenameYesThe file to fetch the contents of.
optionsNoConfiguration options.
options.details NoFetch detailed results (additional headers). Defaults to false.
options.formatNoWhether to fetch binary ("binary") data or textual ("text"). Defaults to "binary".

Options扩展了方法选项

你可以使用onDownloadProgress来计算下载的进度:

import { ProgressEvent } from "webdav";

await client.getFileContents("/package.zip", {
    onDownloadProgress: (progressEvent: ProgressEvent) => {
        // {
        //     total: 12345600,
        //     loaded: 54023
        // }
    }
});

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

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

const downloadLink: string = client.getFileDownloadLink("/image.png");
(filename: string) => string
KEY是否必填描述
filenameYesThe remote file to generate a download link for.

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

const uploadLink: string = client.getFileUploadLink("/image.png");
(filename: string) => string
KEY是否必填描述
filenameYesThe remote file to generate an upload link for.

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

const quota: DiskQuota = await client.getQuota();
// {
//     "used": 1938743,
//     "available": "unlimited"
// }
(options?: GetQuotaOptions) => Promise<DiskQuota | null | ResponseDataDetailed<DiskQuota | null>>
KEY是否必填描述
optionsNoConfiguration options.
options.detailsNoReturn detailed results (headers etc.). Defaults to false.
options.pathNoPath used to make the quota request.

Options扩展了方法选项

锁定远端资源(使用写锁)。

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

// Later
await client.unlock("/file.doc", lock.token);
(path: string, options?: LockOptions) => Promise<LockResponse>
KEY是否必填描述
pathYesThe path to lock.
optionsNoConfiguration options.
options.timeoutNoWebDAV lock requested timeout. See the WebDAV Timeout header documentation.
options.refreshTokenNoPrevious valid lock token that should be refreshed.

Options扩展了方法选项

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

await client.moveFile("/file1.png", "/file2.png");
(filename: string, destinationFilename: string, options?: WebDAVMethodOptions) => Promise<void>
KEY是否必填描述
filenameYesFile to move.
destinationFilenameYesDestination filename.
optionsNoMethod options.

向远程文件写入数据。

当文件未被写入时返回false。{override: false}且文件存在),否则为true。

// Write a buffer:
await client.putFileContents("/my/file.jpg", imageBuffer, { overwrite: false });
// Write a text file:
await client.putFileContents("/my/file.txt", str);

指定maxBodyLength选项来改变客户端可以在请求中发送的最大字节数(仅限NodeJS)。当使用{overwrite: false}时,状态为412的响应将被捕获,并且不会抛出错误。
处理上传进度(仅限浏览器):这使用axios onUploadProgress回调函数,它使用本机XMLHttpRequest进度事件。

// Upload a file and log the progress to the console:
await client.putFileContents("/my/file.jpg", imageFile, { onUploadProgress: progress => {
    console.log(`Uploaded ${progress.loaded} bytes of ${progress.total}`);
} });
(filename: string, data: string | BufferLike | Stream.Readable, options?: PutFileContentsOptions) => Promise<boolean>
KEY是否必填描述
filenameYesFile to write to.
dataYesThe data to write. Can be a string, buffer or a readable stream.
optionsNoConfiguration options.
options.contentLengthNoData content length override. Either a boolean (true (default) = calculate, false = don't set) or a number indicating the exact byte length of the file.
options.overwriteNoWhether or not to override the remote file if it exists. Defaults to true.

Options扩展了方法选项

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

const stat: FileStat = await client.stat("/some/file.tar.gz");
(path: string, options?: StatOptions) => Promise<FileStat | ResponseDataDetailed<FileStat>>
KEY是否必填描述
pathYesRemote path to stat.
optionsNoConfiguration options.
options.detailsNoReturn detailed results (headers etc.). Defaults to false.

Options扩展了方法选项

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

await client.unlock("/file.doc", lock.token);
(path: string, token:string, options?: WebDAVMethodOptions) => Promise<void>
KEY是否必填描述
pathYesRemote path to unlock.
tokenYesToken string from a previous lock request.
optionsNoConfiguration options.

Options扩展了方法选项

Custom properties

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

Method options

大多数WebDAV方法扩展了WebDAVMethodOptions,允许设置自定义头等内容。

KEY是否必填描述
dataNoOptional body/data value to send in the request. This overrides the original body of the request, if applicable.
headersNoOptional headers object to apply to the request. These headers override all others, so be careful.
signalNoInstance of AbortSignal, for aborting requests.

常用数据结构

项目统计

项目统计信息是具有描述文件或目录属性的对象。它们类似如下:

{
    "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"
}

属性:

Property nameTypePresentDescription
filenameStringAlwaysFile path of the remote item
basenameStringAlwaysBase filename of the remote item, no path
lastmodStringAlwaysLast modification date of the item
sizeNumberAlwaysFile size - 0 for directories
typeStringAlwaysItem type - "file" or "directory"
mimeStringFiles onlyMime type - for file items only
etagString / nullWhen supportedETag of the file
propsObjectdetails: trueProps object containing all item properties returned by the server

详细的回答

返回结果的请求,如getDirectoryContents、getFileContents、getQuota和stat,可以配置为返回更详细的信息,如响应头。将{details: true}传递给它们的options参数以接收如下对象:

KEY是否必填描述
data*The data returned by the procedure. Will be whatever type is returned by calling without { details: true }
headersObjectThe response headers.
statusNumberThe numeric status code.
statusTextStringThe status text.

CORS

CORS是浏览器使用的一种安全强制技术,用于确保在预期上下文之间执行请求。如果目标服务器在从浏览器发出请求时没有返回CORS头,则它可能与这个库冲突。处理这件事是你的责任。
众所周知,ownCloud和Nextcloud服务器默认情况下不会返回友好的CORS头文件,这使得在浏览器上下文中无法使用此库。当然,你可以自己强制添加CORS头文件(Apache或Nginx配置),但这样做的风险自负。

Projects using this WebDAV client

Buttercup Password Manager, Nextcloud Server, Nextcloud Photos, ownCloud SDK, React OxIDE, BackItUp


小虫_top
104 声望3 粉丝