1.0.6 • Published 7 months ago

nextcloud-webdav-filepicker v1.0.6

Weekly downloads
19
License
AGPL-3.0
Repository
github
Last release
7 months ago

📂 Nextcloud WebDav file picker

pages

The Nextcloud WebDav file picker is a web component to access Nextcloud files.

It requires the [WebAppPassword](https://apps.nextcloud.com/apps/webapppassword) to be installed on the target Nextcloud server.

Table of Contents

  • [📂 Nextcloud WebDav file picker](#s1)
  • [ 👀 Demo](#s2)
  • [ â–¶ Introduction](#s3)
    • [Features](#s3-1)
    • [Authentication](#s3-2)
    • [How to include it](#s3-3)
  • [ ✨ The wrapper](#s4)
    • [Example](#s4-1)
    • [Methods](#s4-2)
    • [Events](#s4-3)
  • [ 🇻 The Vue component](#s5)
    • [Example](#s5-1)
    • [Props](#s5-2)
    • [Methods](#s5-3)
    • [Slots](#s5-4)
    • [Events](#s5-5)
  • [ 🔧 More information](#s6)
    • [WebAppPassword app and CORS headers](#s6-1)
    • [Restrictions with OAuth access tokens](#s6-2)
    • [Create Nextcloud share links](#s6-3)
    • [Save downloaded files](#s6-4)
    • [Demo pages GET parameters](#s6-5)

👀 Demo

  • [Example of Vue application using the component](https://julien-nc.github.io/nextcloud-webdav-filepicker/examples/with-vue.html)
  • [Example of simple script using the file picker wrapper](https://julien-nc.github.io/nextcloud-webdav-filepicker/examples/without-vue.html)

See how to [pass GET parameters](#demo-pages-get-parameters)

â–¶ Introduction

Features

This file picker is able to

  • Select multiple files and: Get their path Download them as [Files](https://developer.mozilla.org/en-US/docs/Web/API/File) Generate WebDav download links Help you to easily generate Nextcloud share links
  • Select a target directory and: Get its path Generate a WebDav upload link
  • Upload local files

Authentication

🔒 Supported authentication methods are:

  • Provide a login and: a classic password an app password * an OAuth bearer token (see [OAuth token](#restrictions-with-oauth-access-tokens))
  • Let the file picker authenticate on its own with the web login flow

âš  A login is still required if you want to use an OAuth token.

How to include it

There are two ways to include this file picker in your web application:

  • A Vue.js component
  • A wrapper script

The file picker can optionally show buttons to open it an perform actions. You can also directly call the component methods to trigger the file picker actions.

✨ The wrapper

Get it from NPM:

npm install --save nextcloud-webdav-filepicker

And import it:

<script src="[...]/node_modules/nextcloud-webdav-filepicker/js/filePickerWrapper.js"></script>

or

import('[...]/node_modules/nextcloud-webdav-filepicker/js/filePickerWrapper.js').then(() => { main() })

[Complete single file example](https://github.com/julien-nc/nextcloud-webdav-filepicker/blob/master/examples/without-vue.html)

Once you've imported filePickerWrapper.js you can call the window.createFilePicker() function to mount the file picker somewhere in your web page. This function returns the component to let you interact with it later.

Parameters of createFilePicker(mountPoint, options) function:

  • mountPoint (String): the ID of the element in which the file picker is mounted
  • options: initial option values

Accepted options:

keyvaluetypedefault
urlthe Nextcloud base URLstringmandatory
loginthe user namestring-
passwordthe user password, an app password or an OAuth access tokenstring-
accessTokenan OAuth token (use this parameter if you absolutely want to use HTTP Authorization header to authenticate. Using the OAuth token as a password is recommended, see [OAuth token](#restrictions-with-oauth-access-tokens))string-
useCookiesInclude cookies in WebDav and OCS requests if truebooleanfalse
themeColorthe main file picker colorhex color stringNextcloud blue: #0082c9
darkModetoggle the dark themebooleanfalse
displayPreviewstoggle the file preview displaybooleantrue
multipleDownloadlet the user select multiple files in the file pickerbooleantrue
multipleUploadlet the user select multiple local files to uploadbooleantrue
closeOnErrorclose the picker on network error for getFilesLink, uploadFiles and downloadFiles (like when password policy refuses a link password)booleanfalse
enableGetFilesPathshow the "Get files path" buttonbooleanfalse
enableGetFilesLinkshow the "Get files link" buttonbooleanfalse
enableDownloadFilesshow the "Get files link" buttonbooleanfalse
enableGetSaveFilePathshow the "Get files link" buttonbooleanfalse
enableGetUploadFileLinkshow the "Get files link" buttonbooleanfalse
enableUploadFilesshow the "Upload files" buttonbooleanfalse
languageoptional language for translation (xx-XX and xx locales accepted)stringbrowser locale
useWebapppassworduse the webapppassword login flow as fallback when no other method is used or configuredbooleantrue

If login and password/accessToken are not defined, the file picker will let the user authenticate through the web login flow and get an app password by itself.

Example

Here is a minimal example getting files paths and displaying them in the console:

<!-- The component will be mounted there -->
<div id="mount_point"></div>
<!-- Import the wrapper -->
<script src="filePickerWrapper.js"></script>
<script>
	// when the page is loaded
	document.addEventListener('DOMContentLoaded', (event) => {
		// create and mount the component
		const filepicker = window.createFilePicker('mount_point', 'https://my.nextcloud.org')

		// listen to events coming from the component
		document.addEventListener('get-files-path', (e) => {
			console.debug('received "get-files-path" event')
			console.debug(e.detail.selection)
			e.detail.selection.forEach((path) => {
				console.debug(path)
			})
		})
	})
</script>

Methods

You can open the file picker by calling opening methods:

  • getFilesPath: open it to get files paths
  • getFilesLink: open it to get WebDav links, optional parameter: an object with default link option values linkLabel (String) to name the created links expirationDate (Date) protectionPassword (String) allowEdition (bool)
  • downloadFiles: open it to get files content
  • uploadFiles: open the browser file dialog to select local files and then open the filepicker to choose a target directory to upload them
  • getSaveFilePath: open it to get a target directory path
  • getUploadFileLink: open it to select a target directory and get a WebDav upload link

Those are the methods of the filepicker component returned by the window.createFilePicker() function.

const filepicker = window.createFilePicker('mount_point', 'https://my.nextcloud.org')
filepicker.getFilesPath()
filepicker.getFilesLink({
	expirationDate: new Date('2050-01-01'),
	protectionPassword: 'example passwd',
	allowEdition: true,
	linkLabel: 'e-mail attachment to Jane',
})

Events

Here are the events emitted by the component and the data they provide in the detail attribute:

  • filepicker-closed: when the file picker is closed, whatever the reason (no associated data)
  • filepicker-manually-closed: when the user closes the file picker with the top right close icon (no associated data)
  • filepicker-unauthorized: when a WebDav request faced a 401 response code * response: the response object
  • get-files-path: files were selected * selection: an array of file paths
  • files-downloaded: files were downloaded successFiles array of [Files](https://developer.mozilla.org/en-US/docs/Web/API/File) errorFilePaths array of path
  • get-files-link: links were generated
    • shareLinks an array of Nextcloud share links, (only if link creation was successful, see [CORS issue](#create-nextcloud-share-links)), null if failed
    • linkOptions user selected option values for link creation (in case you want to make the OCS requests yourself)
    • pathList list of selected paths
    • ocsUrl OCS API URL to [create Nextcloud share links](#create-nextcloud-share-links)
    • genericShareLink an example of share link with "TOKEN" as the token value
  • get-save-file-path: a target directory was selected * path the path of the selected target directory
  • upload-path-link-generated: WebDav upload link was generated link a WebDav upload link targetDir the target directory path
  • files-uploaded: successFiles array of successfully uploaded [Files](https://developer.mozilla.org/en-US/docs/Web/API/File) errorFiles array of [Files](https://developer.mozilla.org/en-US/docs/Web/API/File) * targetDir the target directory path

You can listen to filepicker events just like other events:

document.addEventListener('filepicker-manually-closed', (e) => {
	console.debug('The file picker was manually closed')
})

🇻 The Vue component

Get it from NPM:

npm install --save nextcloud-webdav-filepicker

And use it:

import NcWebdavFilePicker from 'nextcloud-webdav-filepicker'

[Complete Vue app example](https://github.com/julien-nc/nextcloud-webdav-filepicker/blob/master/src/views/ExampleApp.vue) (top component using the file picker)

Example

Here is a minimal example of a Vue.js app using the file picker:

<template>
	<div id="example-app">
		<h2>My amazing app</h2>
		<NcWebdavFilePicker
			:nc-url="ncUrl"
			@get-files-path="onGetFilesPath">
		</NcWebdavFilePicker>
	</div>
</template>

<script>
import NcWebdavFilePicker from 'nextcloud-webdav-filepicker'

export default {
	name: 'ExampleApp',

	components: { NcWebdavFilePicker },

	props: [],

	data() {
		return {
			ncUrl: 'https://my.nextcloud.org',
		}
	},

	computed: {
	},

	methods: {
		onGetFilesPath(detail) {
			console.debug('files were selected')
			console.debug(detail.selection)
		},
	},
}
</script>

Props

/* === reactive props === */
// Nextcloud base URL
ncUrl: {
	type: String,
	required: true,
},
// Nextcloud user name
ncLogin: {
	type: String,
	default: '',
},
// Nextcloud user password/app password/OAuth access token
ncPassword: {
	type: String,
	default: '',
},
// OAuth access token if you absolutely want to use Bearer Authorization header (if not, using a token as a password works fine)
ncAccessToken: {
	type: String,
	default: '',
},
// Include cookies in WebDav and OCS requests if this is true
useCookies: {
	type: Boolean,
	default: false,
},
// use WebAppPassword login flow
useWebapppassword: {
	type: Boolean,
	default: true,
},
/* === props to control the fp component from the parent one === */
// file picker mode to determine what is done when the picker is opened
pickerMode: {
	type: String,
	default: '',
},
// prop to open the file picker if you don't want to use the buttons
pickerIsOpen: {
	type: Boolean,
	default: false,
},
/* === options === */
// enable multiple selection in all download modes
multipleDownload: {
	type: Boolean,
	default: true,
},
// enable multiple local files selection when uploading
multipleUpload: {
	type: Boolean,
	default: true,
},
// close the picker on network error for getFilesLink, uploadFiles and downloadFiles (like when password policy refuses a link password)
closeOnError: {
	type: Boolean,
	default: false,
},
// file picker title
getTitle: {
	type: String,
	default: null,
},
putTitle: {
	type: String,
	default: null,
},
// theming (reactive too)
themeColor: {
	type: String,
	default: '#0082c9',
	validator: (value) => {
		return value.match(/^#[0-9a-fA-F]{6}$/)
	},
},
darkMode: {
	type: Boolean,
	default: false,
},
displayPreviews: {
	type: Boolean,
	default: true,
},
/* === toggle buttons === */
// display the button to get files path
enableGetFilesPath: {
	type: Boolean,
	default: false,
},
// display the button to get files links
enableGetFilesLink: {
	type: Boolean,
	default: false,
},
// display the button to download files
enableDownloadFiles: {
	type: Boolean,
	default: false,
},
// display the button to get a save file path
enableGetSaveFilePath: {
	type: Boolean,
	default: false,
},
// display the button to get webdav upload link
enableGetUploadFileLink: {
	type: Boolean,
	default: false,
},
// display the button to upload local files
enableUploadFiles: {
	type: Boolean,
	default: false,
},
// optional language for translation (xx-XX and xx locales accepted), use browser locale if null
language: {
	type: String,
	default: null,
},

Methods

You can also open the file picker by calling opening methods:

  • getFilesPath: open it to get files paths
  • getFilesLink: open it to get WebDav links, optional parameter: an object with default link option values linkLabel (String) to name the created links expirationDate (Date) protectionPassword (String) allowEdition (bool)
  • downloadFiles: open it to get files content
  • uploadFiles: open the browser file dialog to select local files and then open the filepicker to choose a target directory to upload them
  • getSaveFilePath: open it to get a target directory path
  • getUploadFileLink: open it to select a target directory and get a WebDav upload link

To access these methods, put a ref to the NcWebdavFilePicker component and then:

this.$refs.myref.getFilesPath()
this.$refs.myref.getFilesLink({
	expirationDate: new Date('2050-01-01'),
	protectionPassword: 'example passwd',
	allowEdition: true,
	linkLabel: 'e-mail attachment to Jane',
})

Slots

There is a slot for each button that triggers a file picker action:

  • get-files-path
  • get-files-link
  • download-files
  • get-save-file-path
  • get-upload-fileLink
  • open-file-input

The click event is catched by the file picker component, no need to listen to it. So you can put whatever you want in those slots, a click anywhere in the slot will open the file picker just like if the default button was clicked.

Events

Those events are emitted by the component and the data included in the associated object:

  • closed: when the file picker is closed, whatever the reason (no associated data)
  • manually-closed: when the user closes the file picker with the top right close icon (no associated data)
  • filepicker-unauthorized: when a WebDav request faced a 401 response code * response: the response object
  • get-files-path: files were selected * selection: an array of file paths
  • files-downloaded: files were downloaded successFiles array of [Files](https://developer.mozilla.org/en-US/docs/Web/API/File) errorFilePaths array of path
  • get-files-link: links were generated shareLinks an array of Nextcloud share links (only if link creation was successful, see [CORS issue](#create-nextcloud-share-links)), null if failed linkOptions user selected option values for link creation (in case you want to make the OCS requests yourself) pathList list of selected paths ocsUrl OCS API URL to [create Nextcloud share links](#create-nextcloud-share-links) * genericShareLink an example of share link with "TOKEN" as the token value
  • get-save-file-path: a target directory was selected * path the path of the selected target directory
  • upload-path-link-generated: WebDav upload link was generated link a WebDav upload link targetDir the target directory path
  • files-uploaded: successFiles array of successfully uploaded [Files](https://developer.mozilla.org/en-US/docs/Web/API/File) errorFiles array of [Files](https://developer.mozilla.org/en-US/docs/Web/API/File) * targetDir the target directory path

🔧 More information

WebAppPassword app and CORS headers

Nextcloud includes restrictive CORS headers preventing browsers to perform API requests. The WebAppPassword app lets Nextcloud admins set a whitelist of allowed origins for WebDav requests. As the file picker will be included in your web application outside of Nextcloud, your website's domain needs to be whilelisted in order to make WebDav requests.

Restrictions with OAuth access tokens

[WebDav client](https://www.npmjs.com/package/webdav) is not able to generate WebDav download/upload links if the authentication is done via Bearer Authorization (if you pass the OAuth token as the ncAccessToken prop). You can still use an OAuth token to authenticate, just use it like a normal password and pass it as the ncPassword prop. As Nextcloud basic auth supports OAuth tokens, everything will work fine.

Create Nextcloud share links

As long as the CORS headers can't be changed on Nextcloud side to allow extra origins (like it's done for WebDav endpoints in WebAppPassword), in most cases, the browser can't make the OCS requests to create new share links on Nextcloud. The file picker will still try to make those requests. They will succeed only if the file picker is used under the same domain as the target Nextcloud. If it fails, you can still do it anywhere else, on the server side of your web application for example. The get-files-link event provides a share link template and the OCS URL to create such share links. The OCS API endpoint looks like https://my.nextcloud.org/ocs/v2.php/apps/files_sharing/api/v1/shares.

Here is an example of link creation that you can do on your server side:

curl -H "OCS-APIRequest: true" -u login:token -X POST -d "path=/path/to/file&shareType=3" "$OCS_URL"

This will create and return a share link (shareType=3) with default permissions. The share token can be found in ocs.data.token of the JSON response. Then just place the token in the share link template. For example, if get-files-link gave you https://my.nextcloud.org/index.php/s/TOKEN as share link template and the token of the link you created is wHx2BteGayciKiA, then the share link is https://my.nextcloud.org/index.php/s/wHx2BteGayciKiA.

Just append /download to the share link to trigger the file download instead of displaying the share page.

Save downloaded files

You can allow users to save the files downloaded by the file picker. As the returned objects are Files (subclass of Blobs), you can use [file-saver](https://www.npmjs.com/package/file-saver) to open a save file dialog and let the browser write the files to local filesystem.

Demo pages GET parameters

You can pass GET parameters to demo pages in order to initialize field values. It makes it easier to provide demo links directly working. For example:

https://julien-nc.github.io/nextcloud-webdav-filepicker/examples/with-vue.html?url=https://my.nextcloud.org&login=jason&password=Nm8cC-kHczM-HGz55-S9SE2-Frf4F&color=aa82c9&darkMode=1 (url, login and password are examples)

Accepted parameters are:

  • url
  • login
  • password
  • accessToken
  • color (hex color without hash prefix, example: 'aa82c9')
  • darkMode ('1' is true, anything else is false)
1.0.6

7 months ago

1.0.5

1 year ago

1.0.2

1 year ago

1.0.4

1 year ago

1.0.3

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago

0.0.26

2 years ago

0.0.27

2 years ago

0.0.24

2 years ago

0.0.23

2 years ago

0.0.22

2 years ago

0.0.20

3 years ago

0.0.21

3 years ago

0.0.19

3 years ago

0.0.18

3 years ago

0.0.16

3 years ago

0.0.15

3 years ago

0.0.14

3 years ago

0.0.13

3 years ago

0.0.12

3 years ago

0.0.11

3 years ago

0.0.10

3 years ago

0.0.9

3 years ago

0.0.8

3 years ago

0.0.7

3 years ago

0.0.6

3 years ago

0.0.5

3 years ago

0.0.4

3 years ago