• Stars
    star
    157
  • Rank 238,399 (Top 5 %)
  • Language
    JavaScript
  • Created over 9 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Cross-browser directory and multi-file upload library

uppie

Cross-browser file and directory and upload library

uppie is a tiny JavaScript library which helps you with file and directory uploads in browsers. It supports all current and past implementations of multi-file and directory uploads and provides you with a FormData object you can submit directly to a server through either XMLHttpRequest or fetch. Both the <input type="file"> element and drag-and-drop are supported.

Usage

npm install uppie
import {uppie} from 'uppie';

uppie(document.querySelector('#file'), async (e, formData, files) => {
  await fetch('/upload', {method: 'POST', body: formData});
});

Browser support

files via input[type=file] files via DnD directories via input[type=file] directories via DnD
Firefox yes yes yes (50+) yes (50+)
Chrome yes yes yes (29+) yes (29+)
Edge yes yes yes (13+) yes (14+)
Safari yes yes yes (11.1+) yes (11.1+)

Notes

  • Empty directories are excluded from the results by all browsers as dictated by the spec.
  • Firefox and Safari exclude files and directories starting with a ..

API

uppie(node, [opts], callback)

  • node Node or NodeList: One or more DOM nodes. If a <input type="file"> is given, uppie will monitor it for change events. Any other element type will be enabled as a dropzone and watched for drop events. If you want to use both on the same element, use a hidden <input> and forward the click event.
  • opts Object: A options object which can contain:
    • name: The name attribute for creating the FormData entries. Default: "files[]".
  • callback Function: callback which is called every time the selected files change or when files are dropped in the dropzone.

The callback receives

  • event Event: the original event. Useful for calling event.stopPropagation().
  • formData FormData: FormData object to be used for XHR2 uploading.
  • files Array: Array of paths for preview purposes.

FormData format

name defaults to "files[]", filename will be the full path to the file, with / used as path separator. Does not include a leading slash. Make sure to sanitize filename on the server before writing it to the disk to prevent exploits involving .. in the path. Example FormData:

------Boundary
Content-Disposition: form-data; name="files[]"; filename="docs/1.txt"
Content-Type: text/plain

[DATA]
------Boundary
Content-Disposition: form-data; name="files[]"; filename="docs/path/2.txt"
Content-Type: text/plain

[DATA]
------Boundary
Content-Disposition: form-data; name="files[]"; filename="docs/path/to/3.txt"
Content-Type: text/plain

Recommended input element attributes

  • multiple: allow multiple files or directories to be selected.
  • webkitdirectory: enable directory uploads.

PHP example

Below is example for PHP 7.0 and possibly earlier versions. PHP does not parse the path from the filename field, so it is necessary to submit the path through other means, like as separate FormData fields as done in the example.

import {uppie} from 'uppie';

const uppie = new Uppie();

uppie(document.documentElement, (event, formData, files) => {
  files.forEach(path => {
    formData.append("paths[]", path);
  });

  const xhr = new XMLHttpRequest();
  xhr.open('POST', 'upload.php');
  xhr.send(formData);
});

And in upload.php:

foreach ($_FILES['files']['name'] as $i => $name) {
  if (strlen($_FILES['files']['name'][$i]) > 1) {
    $fullpath = strip_tags($_POST['paths'][$i]);
    $path = dirname($fullpath);

    if (!is_dir('uploads/'.$path)){
      mkdir('uploads/'.$path);
    }
    if (move_uploaded_file($_FILES['files']['tmp_name'][$i], 'uploads/'.$fullpath)) {
        echo '<li>'.$name.'</li>';
    }
  }
}

Note that PHP's upload limits might need to be raised depending on use case.

Β© silverwind, distributed under BSD licence

More Repositories

1

droppy

**ARCHIVED** Self-hosted file storage
JavaScript
1,597
star
2

oui

Look up MAC addresses for their vendor in the IEEE OUI database
JavaScript
97
star
3

updates

Flexible npm and poetry dependency update tool
JavaScript
88
star
4

default-gateway

Get the default network gateway, cross-platform.
JavaScript
85
star
5

cidr-tools

Tools to work with IPv4 and IPv6 CIDR
JavaScript
64
star
6

tcpie

CLI tool to ping any TCP port
JavaScript
52
star
7

idTip

WoW Addon: Adds IDs to the ingame tooltips
Lua
39
star
8

is-cidr

Check if a string is an IP address in CIDR notation
TypeScript
34
star
9

cidr-regex

Regular expression for matching IP addresses in CIDR notation
TypeScript
31
star
10

file-extension

Get the extension of a given filename or path
Makefile
30
star
11

port-numbers

npm module that holds information on network port numbers based on IANA's data.
JavaScript
30
star
12

precompress

Generate pre-compressed .gz and .br files for static web servers
JavaScript
29
star
13

daemonize-process

Daemonize the current Node.js process
JavaScript
29
star
14

pagediff

Visually diff websites
JavaScript
21
star
15

dnsbl

Query DNS-based blackhole lists
JavaScript
19
star
16

dotfiles

My dotfiles for zsh, vim, git, mintty and more.
Shell
14
star
17

save-csv

Download an array of objects as a CSV file in the browser
JavaScript
13
star
18

rrdir

Recursive directory reader with a delightful API
JavaScript
13
star
19

expect-telnet

telnet automation through expect-send sequences, like in Tcl
JavaScript
13
star
20

root-hints

Provides IP addresses of the DNS root server, aka root hints
JavaScript
12
star
21

versions

CLI to flexibly increment a project's version
JavaScript
12
star
22

ip-bigint

Convert IPv4 and IPv6 addresses to native BigInt and vice-versa
JavaScript
10
star
23

fetch-css

Extract CSS from websites and browser extensions
JavaScript
9
star
24

remap-css

Remap CSS rules based on declaration value
JavaScript
9
star
25

rebirth

Restart a node process from within itself
JavaScript
8
star
26

cidr-range

Get an array of IP addresses for a given CIDR range
JavaScript
8
star
27

caa

rfc6844-conform CAA record lookup and validation
JavaScript
8
star
28

clippie

Teeny-tiny browser clipboard copy
TypeScript
8
star
29

cfdns

CLI to modify DNS records hosted on Cloudflare
JavaScript
7
star
30

armhf-registry

Minimal Docker Registry image the ARM architecture
Makefile
7
star
31

oui-data

IEEE OUI database as JSON
JavaScript
6
star
32

detect-engine

Detect whether you're running on node.js or io.js
JavaScript
6
star
33

dnsz

Generic DNS zone file parser and stringifier
JavaScript
6
star
34

fetch-bench

Benchmark of node `fetch` implementations
JavaScript
6
star
35

as-networks

Get all CIDR networks contained in an autonomous system
JavaScript
5
star
36

fetch-enhanced

fetch wrapper with support for automatic HTTP proxy and timeout
JavaScript
5
star
37

eslint-config-silverwind

Exhaustive ESLint configuration
Makefile
5
star
38

ocsp.sh

Shell script to retrieve a OCSP responses via curl
Shell
5
star
39

react-svg-raw

React Component for wrapper-less inline SVGs
JavaScript
4
star
40

ip-ptr

Get the PTR name for a given IPv4 or IPv6 address
JavaScript
4
star
41

multi-ldap

UNMAINTAINED - ldapjs client wrapper with support for multiple servers
JavaScript
4
star
42

timerel

Teeny-tiny relative date formatting
TypeScript
3
star
43

parse-listen-string

Parse a HTTP server listen string
TypeScript
3
star
44

dhparam

Generate PEM-encoded Diffie-Hellman parameters directly from within node
JavaScript
3
star
45

overlay-scrollbars

Transparent overlay scrollbars for Firefox
CSS
3
star
46

squery

Yet another jQuery alternative
JavaScript
3
star
47

glowie

Teeny-tiny terminal color library which does not perform any color support detection
TypeScript
2
star
48

is-cli

*Deprecated - Please use es-main module or similar* Detect if the current script was ran as a CLI
JavaScript
2
star
49

globalrequire

INACTIVE - please use https://github.com/sindresorhus/import-global
JavaScript
2
star
50

stylelint-config-silverwind

Extensive stylelint configuration
Makefile
2
star
51

symlink-test

Just testing symlinks inside a git repo
JavaScript
2
star
52

deepie-merge

Yay, another deep merge
TypeScript
2
star
53

emoji-markdown-tests

1
star
54

vite-string-plugin

Vite plugin to import files as string, with zero dependencies
TypeScript
1
star
55

eslint-config-silverwind-typescript

Exhaustive ESLint configuration with typescript
Makefile
1
star
56

tmtheme

My Sublime Text theme
Makefile
1
star
57

eslint-config-silverwind-react

Exhausive ESLint React configuration
Makefile
1
star
58

vitest-config-silverwind

Shared vitest configuration
TypeScript
1
star
59

typescript-config-silverwind

Makefile
1
star
60

vite-import-meta

JavaScript
1
star
61

vite-config-silverwind

Shared vite configuration
TypeScript
1
star