UNPKG

12.9 kBMarkdownView Raw
1![WebDAV](https://raw.githubusercontent.com/perry-mitchell/webdav-client/master/webdav.jpg)
2
3> A WebDAV client written in JavaScript for NodeJS and the browser.
4
5[![Build Status](https://travis-ci.org/perry-mitchell/webdav-client.svg?branch=master)](https://travis-ci.org/perry-mitchell/webdav-client) [![npm version](https://badge.fury.io/js/webdav.svg)](https://www.npmjs.com/package/webdav) [![monthly downloads](https://img.shields.io/npm/dm/webdav.svg)](https://www.npmjs.com/package/webdav) [![total downloads](https://img.shields.io/npm/dt/webdav.svg?label=total%20downloads)](https://www.npmjs.com/package/webdav)
6
7## About
8
9WebDAV is a well-known, stable and highly flexible protocol for interacting with remote filesystems via an API. Being that it is so widespread, many file hosting services such as **Box**, **ownCloud**/**Nextcloud** and **Yandex** use it as a fallback to their other interfaces.
10
11This library provides a **WebDAV client** interface that makes interacting with WebDAV enabled services easy. The API returns promises and resolve with the results. It parses and prepares directory-contents requests for easy consumption, as well as providing methods for fetching things like file stats and quotas.
12
13Please read the [contribution guide](CONTRIBUTING.md) if you plan on making an issue or PR.
14
15### Node support
16
17This library is compatibale with **NodeJS version 10** and above (For version 6/8 support, use versions in the range of `2.*`. For version 4 support, use versions in the range of `1.*`). Version 2.x is now in maintenance mode and will receive no further feature additions. It will receive the odd bug fix when necessary. Version 1.x is no longer supported.
18
19### Usage in the Browser
20
21As of version 3, WebDAV client is now supported in the browser. The compilation settings specify a minimum supported browser version of Internet Explorer 11, however testing in this browser is not performed regularly.
22
23_Although you may choose to transpile this library's default entry point (NodeJS) yourself, it is not advised - use the dedicated web version instead._
24
25You can use the web version via a different entry point:
26
27```javascript
28import { createClient } from "webdav/web";
29```
30
31The browser version uses a UMD-style module definition, meaning you can simply load the library within your browser using a `<script>` tag. When using this method the library is made available on the window object as such: `window.WebDAV`. For example:
32
33```javascript
34const client = window.WebDAV.createClient(/* ... */);
35```
36
37**NB:** Streams are not available within the browser, so `createReadStream` and `createWriteStream` are just stubbed. Calling them will throw an exception.
38
39## Installation
40
41Simple install as a dependency using npm:
42
43```
44npm install webdav --save
45```
46
47## Usage
48
49Usage entails creating a client adapter instance by calling the factory function `createClient`:
50
51```javascript
52const { createClient } = require("webdav");
53
54const client = createClient(
55 "https://webdav.example.com/marie123",
56 {
57 username: "marie",
58 password: "myS3curePa$$w0rd"
59 }
60);
61
62// Get directory contents
63const directoryItems = await client.getDirectoryContents("/");
64// Outputs a structure like:
65// [{
66// filename: "/my-file.txt",
67// basename: "my-file.txt",
68// lastmod: "Mon, 10 Oct 2018 23:24:11 GMT",
69// size: 371,
70// type: "file"
71// }]
72```
73
74Make sure to read the [API documentation](API.md) for more information on the [available adapter methods](API.md#ClientInterface).
75
76### Authentication & Connection
77
78`webdav` uses `Basic` authentication by default, if `username` and `password` are provided (if none are provided, no `Authorization` header is specified). It also supports OAuth tokens and Digest auth.
79
80#### Basic or no authentication
81
82You can use the client without authentication if the server doesn't require it - simply avoid passing any values to `username`, `password`, `token` or `digest` in the config.
83
84To use basic authentication, simply pass a `username` and `password` in the config.
85
86`webdav` also allows for overriding the built in HTTP and HTTPS agents by setting the properties `httpAgent` & `httpsAgent` accordingly. These should be instances of node's [http.Agent](https://nodejs.org/api/http.html#http_class_http_agent) and [https.Agent](https://nodejs.org/api/https.html#https_class_https_agent) respectively.
87
88#### OAuth tokens
89
90To use a token to authenticate, simply pass the token data to the `token` field:
91
92```javascript
93createClient(
94 "https://address.com",
95 {
96 token: {
97 "access_token": "2YotnFZFEjr1zCsicMWpAA",
98 "token_type": "example",
99 "expires_in": 3600,
100 "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
101 "example_parameter": "example_value"
102 }
103 }
104);
105```
106
107#### Digest authentication
108
109If a server requires digest-based authentication, you can enable this functionality by setting `digest` to true:
110
111```javascript
112createClient(
113 "https://address.com",
114 {
115 username: "someUser",
116 password: "myS3curePa$$w0rd",
117 digest: true
118 }
119);
120```
121
122### Methods
123
124#### copyFile
125
126Copy a file from one remote location to another:
127
128```javascript
129await client.copyFile("/sub/item.txt", "/destination/item.txt");
130```
131
132#### createDirectory
133
134Create a new directory:
135
136```javascript
137await client.createDirectory("/completely/new/path");
138```
139
140#### createReadStream
141
142Create a read stream targeted at a remote file:
143
144```javascript
145client
146 .createReadStream("/video.mp4")
147 .pipe(fs.createWriteStream("~/video.np4"));
148```
149
150#### createWriteStream
151
152Create a write stream targeted at a remote file:
153
154```javascript
155fs.createReadStream("~/Music/song.mp3")
156 .pipe(client.createWriteStream("/music/song.mp3"));
157```
158
159#### deleteFile
160
161Delete a remote file:
162
163```javascript
164await client.deleteFile("/tmp.dat");
165```
166
167### exists
168
169Check if a file or directory exists:
170
171```javascript
172if (await client.exists("/some/path") === false) {
173 await client.createDirectory("/some/path");
174}
175```
176
177#### getDirectoryContents
178
179Get the contents of a remote directory. Returns an array of [item stats](#item-stat).
180
181```javascript
182// Get current directory contents:
183const contents = await client.getDirectoryContents("/");
184// Get all contents:
185const contents = await client.getDirectoryContents("/", { deep: true });
186```
187
188Files can be globbed using the `glob` option (processed using [`minimatch`](https://github.com/isaacs/minimatch)). When using a glob pattern it is recommended to fetch `deep` contents:
189
190```javascript
191const images = await client.getDirectoryContents("/", { deep: true, glob: "/**/*.{png,jpg,gif}" });
192```
193
194#### getFileContents
195
196Fetch the contents of a remote file. Binary contents are returned by default (Buffer):
197
198```javascript
199const buff = await client.getFileContents("/package.zip");
200```
201
202It is recommended to use streams if the files being transferred are large.
203
204Text files can also be fetched:
205
206```javascript
207const str = await client.getFileContents("/config.json", { format: "text" });
208```
209
210#### getFileDownloadLink
211
212Return a public link where a file can be downloaded. **This exposes authentication details in the URL**.
213
214```javascript
215const downloadLink = client.getFileDownloadLink("/image.png");
216```
217
218_Not all servers may support this feature. Only Basic authentication and unauthenticated connections support this method._
219
220#### getFileUploadLink
221
222Return a URL for a file upload:
223
224```javascript
225const uploadLink = client.getFileUploadLink("/image.png");
226```
227
228_See `getFileDownloadLink` for support details._
229
230#### getQuota
231
232Get the quota information for the current account:
233
234```javascript
235const quota = await client.getQuota();
236// {
237// "used": 1938743,
238// "available": "unlimited"
239// }
240```
241
242#### moveFile
243
244Move a remote file to another remote location:
245
246```javascript
247await client.moveFile("/file1.png", "/file2.png");
248```
249
250#### putFileContents
251
252Write data to a remote file:
253
254```javascript
255// Write a buffer:
256await client.putFileContents("/my/file.jpg", imageBuffer, { overwrite: false });
257// Write a text file:
258await client.putFileContents("/my/file.txt", str);
259```
260
261Handling Upload Progress (browsers only):
262*This uses the axios onUploadProgress callback which uses the native XMLHttpRequest [progress event](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequestEventTarget/onprogress).*
263
264```javascript
265// Upload a file and log the progress to the console:
266await client.putFileContents("/my/file.jpg", imageFile, { onUploadProgress: progress => {
267 console.log(`Uploaded ${progress.loaded} bytes of ${progress.total}`);
268} });
269```
270
271#### stat
272
273Get a file or directory stat object:
274
275```javascript
276const stat = await client.stat("/some/file.tar.gz");
277```
278
279Returns an [item stat](#item-stat).
280
281### Custom requests
282
283Custom requests can be made to the attached host:
284
285```javascript
286const contents = await client.customRequest("/alrighty.jpg", {
287 method: "PROPFIND",
288 headers: {
289 Accept: "text/plain",
290 Depth: 0
291 },
292 responseType: "text"
293});
294```
295
296### Returned data structures
297
298#### Directory contents items
299
300Each item returned by `getDirectoryContents` is basically an [item stat](#item-stat). If the `details: true` option is set, each item stat (as mentioned in the stat documentation) will also include the `props` property containing extra properties returned by the server. No particular property in `props`, not its format or value, is guaranteed.
301
302You can request all files in the file-tree (infinite depth) by calling `getDirectoryContents` with the option `deep: true`. All items will be returned in a flat array, where the `filename` will hold the absolute path.
303
304#### Detailed responses
305
306Requests that return results, such as `getDirectoryContents`, `getFileContents`, `getQuota` and `stat`, can be configured to return more detailed information, such as response headers. Pass `{ details: true }` to their options argument to receive an object like the following:
307
308| Property | Type | Description |
309|--------------|-----------------|----------------------------------------|
310| data | * | The data returned by the procedure. Will be whatever type is returned by calling without `{ details: true }` |
311| headers | Object | The response headers. |
312
313#### Item stat
314
315Item stats are objects with properties that descibe a file or directory. They resemble the following:
316
317```json
318{
319 "filename": "/test",
320 "basename": "test",
321 "lastmod": "Tue, 05 Apr 2016 14:39:18 GMT",
322 "size": 0,
323 "type": "directory",
324 "etag": null
325}
326```
327
328or:
329
330```json
331{
332 "filename": "/image.jpg",
333 "basename": "image.jpg",
334 "lastmod": "Sun, 13 Mar 2016 04:23:32 GMT",
335 "size": 42497,
336 "type": "file",
337 "mime": "image/jpeg",
338 "etag": "33a728c7f288ede1fecc90ac6a10e062"
339}
340```
341
342Properties:
343
344| Property name | Type | Present | Description |
345|---------------|---------|--------------|---------------------------------------------|
346| filename | String | Always | File path of the remote item |
347| basename | String | Always | Base filename of the remote item, no path |
348| lastmod | String | Always | Last modification date of the item |
349| size | Number | Always | File size - 0 for directories |
350| type | String | Always | Item type - "file" or "directory" |
351| mime | String | Files only | Mime type - for file items only |
352| etag | String / null | When supported | [ETag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) of the file |
353| props | Object | `details: true` | Props object containing all item properties returned by the server |
354
355## Compatibility
356This library has been tested to work with the following WebDAV servers or applications:
357
358 * [ownCloud](https://owncloud.org/) ¹
359 * [Nextcloud](https://nextcloud.com/) ¹
360 * [Yandex.ru](https://yandex.ru/)
361 * [jsDAV](https://github.com/mikedeboer/jsDAV)
362 * [webdav-server](https://github.com/OpenMarshal/npm-WebDAV-Server)
363
364 ¹ These services will work if CORS is correctly configured to return the proper headers. This may not work by default.
365
366### CORS
367CORS is a security enforcement technique employed by browsers to ensure requests are executed to and from expected contexts. It can conflict with this library if the target server doesn't return CORS headers when making requests from a browser. It is your responsibility to handle this.
368
369It is a known issue that ownCloud and Nextcloud servers by default don't return friendly CORS headers, making working with this library within a browser context impossible. You can of course force the addition of CORS headers (Apache or Nginx configs) yourself, but do this at your own risk.