nextcloud-webdav-filepicker
v1.0.6
Published
Nextcloud WebDav file picker
Downloads
115
Readme
📂 Nextcloud WebDav file picker
The Nextcloud WebDav file picker is a web component to access Nextcloud files.
It requires the WebAppPassword to be installed on the target Nextcloud server.
Table of Contents
- 📂 Nextcloud WebDav file picker
- 👀 Demo
- ▶ Introduction
- ✨ The wrapper
- 🇻 The Vue component
- 🔧 More information
👀 Demo
- Example of Vue application using the component
- Example of simple script using the file picker wrapper
See how to pass GET parameters
▶ Introduction
Features
This file picker is able to
- Select multiple files and:
- Get their path
- Download them as Files
- 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)
- 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() })
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:
| key | value | type | default |
| -- | -- | -- | -- |
| url | the Nextcloud base URL | string | mandatory |
| login | the user name | string | - |
| password | the user password, an app password or an OAuth access token | string | - |
| accessToken | an 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) | string | - |
| useCookies | Include cookies in WebDav and OCS requests if true | boolean | false |
| themeColor | the main file picker color | hex color string | Nextcloud blue: #0082c9
|
| darkMode | toggle the dark theme | boolean | false
|
| displayPreviews | toggle the file preview display | boolean | true
|
| multipleDownload | let the user select multiple files in the file picker | boolean | true
|
| multipleUpload | let the user select multiple local files to upload | boolean | true
|
| closeOnError | close the picker on network error for getFilesLink, uploadFiles and downloadFiles (like when password policy refuses a link password) | boolean | false
|
| enableGetFilesPath | show the "Get files path" button | boolean | false
|
| enableGetFilesLink | show the "Get files link" button | boolean | false
|
| enableDownloadFiles | show the "Get files link" button | boolean | false
|
| enableGetSaveFilePath | show the "Get files link" button | boolean | false
|
| enableGetUploadFileLink | show the "Get files link" button | boolean | false
|
| enableUploadFiles | show the "Upload files" button | boolean | false
|
| language | optional language for translation (xx-XX and xx locales accepted) | string | browser locale |
| useWebapppassword | use the webapppassword login flow as fallback when no other method is used or configured | boolean | true
|
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 linksexpirationDate
(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 coderesponse
: the response object
get-files-path
: files were selectedselection
: an array of file paths
files-downloaded
: files were downloadedsuccessFiles
array of FileserrorFilePaths
array of path
get-files-link
: links were generatedshareLinks
an array of Nextcloud share links, (only if link creation was successful, see CORS issue),null
if failedlinkOptions
user selected option values for link creation (in case you want to make the OCS requests yourself)pathList
list of selected pathsocsUrl
OCS API URL to create Nextcloud share linksgenericShareLink
an example of share link with "TOKEN" as the token value
get-save-file-path
: a target directory was selectedpath
the path of the selected target directory
upload-path-link-generated
: WebDav upload link was generatedlink
a WebDav upload linktargetDir
the target directory path
files-uploaded
:
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 (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 linksexpirationDate
(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 coderesponse
: the response object
get-files-path
: files were selectedselection
: an array of file paths
files-downloaded
: files were downloadedsuccessFiles
array of FileserrorFilePaths
array of path
get-files-link
: links were generatedshareLinks
an array of Nextcloud share links (only if link creation was successful, see CORS issue),null
if failedlinkOptions
user selected option values for link creation (in case you want to make the OCS requests yourself)pathList
list of selected pathsocsUrl
OCS API URL to create Nextcloud share linksgenericShareLink
an example of share link with "TOKEN" as the token value
get-save-file-path
: a target directory was selectedpath
the path of the selected target directory
upload-path-link-generated
: WebDav upload link was generatedlink
a WebDav upload linktargetDir
the target directory path
files-uploaded
:
🔧 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 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 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)