docs: add back markdown files (#5064)

This commit is contained in:
Antoine du Hamel 2024-04-16 15:24:58 +02:00 committed by GitHub
parent 64a8f0601c
commit b115b3621b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
56 changed files with 13086 additions and 0 deletions

View file

@ -413,8 +413,15 @@ module.exports = {
files: ['**/*.md', '*.md'],
processor: 'markdown/markdown',
},
{
files: ['docs/**/*.md/*.js'],
parserOptions: {
sourceType: 'module',
},
},
{
files: ['**/*.md/*.js', '**/*.md/*.javascript'],
excludedFiles: ["docs/**/*"],
parserOptions: {
sourceType: 'module',
},

View file

@ -77,3 +77,24 @@ jobs:
run: corepack yarn workspaces focus @uppy-dev/build
- name: Run linter
run: corepack yarn run lint:markdown
lint_docs:
name: Lint Docs
runs-on: ubuntu-latest
steps:
- name: Checkout Uppy.io sources
uses: actions/checkout@v3
with:
repository: transloadit/uppy.io
- run: rm -rf docs # the other PR has not landed
- name: Checkout docs
uses: actions/checkout@v3
with:
path: uppy
- run: mv uppy /tmp/uppy && ln -s /tmp/uppy/docs docs
- name: Install dependencies
run: corepack yarn --immutable
- name: Lint files
run: corepack yarn lint
- name: Test build website
run: corepack yarn build

View file

@ -12,5 +12,12 @@ module.exports = {
semi: true,
},
},
{
files: "docs/**",
options: {
semi: true,
useTabs: true,
}
}
],
}

3
docs/README.md Normal file
View file

@ -0,0 +1,3 @@
# Uppy documentation
To build the documentation, see <https://github.com/transloadit/uppy.io>.

935
docs/companion.md Normal file
View file

@ -0,0 +1,935 @@
---
sidebar_position: 4
---
# Companion
Companion is an open source server application which **takes away the complexity
of authentication and the cost of downloading files from remote sources**, such
as Instagram, Google Drive, and others. Companion is a server-to-server
orchestrator that streams files from a source to a destination, and files are
never stored in Companion. Companion can run either as a standalone
(self-hosted) application, [Transloadit-hosted](#hosted), or plugged in as an
Express middleware into an existing application. The Uppy client requests remote
files from Companion, which it will download and simultaneously upload to your
[Tus server](/docs/tus), [AWS bucket](/docs/aws-s3), or any server that supports
[PUT, POST or Multipart uploads](/docs/xhr-upload).
This means a user uploading a 5GB video from Google Drive from their phone isnt
eating into their data plans and you dont have to worry about implementing
OAuth.
## When should I use it?
If you want to let users download files from [Box][], [Dropbox][], [Facebook][],
[Google Drive][googledrive], [Instagram][], [OneDrive][], [Unsplash][], [Import
from URL][url], or [Zoom][] — you need Companion.
Companion supports the same [uploaders](/docs/guides/choosing-uploader) as Uppy:
[Tus](/docs/tus), [AWS S3](/docs/aws-s3), and [regular multipart](/docs/tus).
But instead of manually setting a plugin, Uppy sends along a header with the
uploader and Companion will use the same on the server. This means if you are
using [Tus](/docs/tus) for your local uploads, you can send your remote uploads
to the same Tus server (and likewise for your AWS S3 bucket).
:::note
Companion only deals with _remote_ files, _local_ files are still uploaded from
the client with your upload plugin.
:::
## Hosted
Using [Transloadit][] services comes with a hosted version of Companion so you
dont have to worry about hosting your own server. Whether you are on a free or
paid Transloadit [plan](https://transloadit.com/pricing/), you can use
Companion. Its not possible to rent a Companion server without a Transloadit
plan.
[**Sign-up for a (free) plan**](https://transloadit.com/pricing/).
:::tip
Choosing Transloadit for your file services also comes with credentials for all
remote providers. This means you dont have to waste time going through the
approval process of every app. You can still add your own credentials in the
Transloadit admin page if you want.
:::
:::info
Downloading and uploading files through Companion doesnt count towards your
[monthly quota](https://transloadit.com/docs/faq/1gb-worth/), its a way for
files to arrive at Transloadit servers, much like Uppy.
:::
## Installation & use
Companion is installed from npm. Depending on how you want to run Companion, the
install process is slightly different. Companion can be integrated as middleware
into your [Express](https://expressjs.com/) app or as a standalone server. Most
people probably want to run it as a standalone server, while the middleware
could be used to further customise Companion or integrate it into your own HTTP
server code.
:::note
Since v2, you need to be running `node.js >= v10.20.1` to use Companion. More
information in the
[migrating to 2.0](/docs/guides/migration-guides/#migrate-from-uppy-1x-to-2x)
guide.
Windows is not a supported platform right now. It may work, and were happy to
accept improvements in this area, but we cant provide support.
:::
### Standalone mode
You can use the standalone version if you want to run Companion as its own
Node.js process. Its a configured Express server with sessions, logging, and
security best practices. First youll typically want to install it globally:
```bash
npm install -g @uppy/companion
```
Standalone Companion will always serve HTTP (not HTTPS) and expects a reverse
proxy with SSL termination in front of it when running in production. See
[`COMPANION_PROTOCOL`](#server) for more information.
Companion ships with an executable file (`bin/companion`) which is the
standalone server. Unlike the middleware version, options are set via
environment variables.
:::info
Checkout [options](#options) for the available options in JS and environment
variable formats.
:::
You need at least these three to get started:
```bash
export COMPANION_SECRET="shh!Issa Secret!"
export COMPANION_DOMAIN="YOUR SERVER DOMAIN"
export COMPANION_DATADIR="PATH/TO/DOWNLOAD/DIRECTORY"
```
Then run:
```bash
companion
```
You can also pass in the path to your JSON config file, like so:
```bash
companion --config /path/to/companion.json
```
You may also want to run Companion in a process manager like
[PM2](https://pm2.keymetrics.io/) to make sure it gets restarted on upon
crashing as well as allowing scaling to many instances.
### Express middleware mode
First install it into your Node.js project with your favorite package manager:
```bash
npm install @uppy/companion
```
To plug Companion into an existing server, call its `.app` method, passing in an
[options](#options) object as a parameter. This returns a server instance that
you can mount on a route in your Express app.
```js
import express from 'express';
import bodyParser from 'body-parser';
import session from 'express-session';
import companion from '@uppy/companion';
const app = express();
// Companion requires body-parser and express-session middleware.
// You can add it like this if you use those throughout your app.
//
// If you are using something else in your app, you can add these
// middlewares in the same subpath as Companion instead.
app.use(bodyParser.json());
app.use(session({ secret: 'some secrety secret' }));
const companionOptions = {
providerOptions: {
drive: {
key: 'GOOGLE_DRIVE_KEY',
secret: 'GOOGLE_DRIVE_SECRET',
},
},
server: {
host: 'localhost:3020',
protocol: 'http',
// Default installations normally don't need a path.
// However if you specify a `path`, you MUST specify
// the same path in `app.use()` below,
// e.g. app.use('/companion', companionApp)
// path: '/companion',
},
filePath: '/path/to/folder/',
};
const { app: companionApp } = companion.app(companionOptions);
app.use(companionApp);
```
Companion uses WebSockets to communicate progress, errors, and successes to the
client. This is what Uppy listens to to update its internal state and UI.
Add the Companion WebSocket server using the `companion.socket` function:
```js
const server = app.listen(PORT);
companion.socket(server);
```
If WebSockets fail for some reason Uppy and Companion will fallback to HTTP
polling.
### Running many instances
We recommend running at least two instances in production, so that if the
Node.js event loop gets blocked by one or more requests (due to a bug or spike
in traffic), it doesnt also block or slow down all other requests as well (as
Node.js is single threaded).
As an example for scale, one enterprise customer of Transloadit, who self-hosts
Companion to power an education service that is used by many universities
globally, deploys 7 Companion instances. Their earlier solution ran on 35
instances. In our general experience Companion will saturate network interface
cards before other resources on commodity virtual servers (`c5d.2xlarge` for
instance).
Your mileage may vary, so we recommend to add observability. You can let
Prometheus crawl the `/metrics` endpoint and graph that with Grafana for
instance.
#### Using unique endpoints
One option is to run many instances with each instance having its own unique
endpoint. This could be on separate ports, (sub)domain names, or IPs. With this
setup, you can either:
1. Implement your own logic that will direct each upload to a specific Companion
endpoint by setting the `companionUrl` option
2. Setting the Companion option `COMPANION_SELF_ENDPOINT`. This option will
cause Companion to respond with a `i-am` HTTP header containing the value
from `COMPANION_SELF_ENDPOINT`. When Uppys sees this header, it will pin all
requests for the upload to this endpoint.
In either case, you would then also typically configure a single Companion
instance (one endpoint) to handle all OAuth authentication requests, so that you
only need to specify a single OAuth callback URL. See also `oauthDomain` and
`validHosts`.
#### Using a load balancer
The other option is to set up a load balancer in front of many Companion
instances. Then Uppy will only see a single endpoint and send all requests to
the associated load balancer, which will then distribute them between Companion
instances. The companion instances coordinate their messages and events over
Redis so that any instance can serve the clients requests. Note that sticky
sessions are **not** needed with this setup. Here are the requirements for this
setup:
* The instances need to be connected to the same Redis server.
* You need to set `COMPANION_SECRET` to the same value on both servers.
* if you use the `companionKeysParams` feature (Transloadit), you also need
`COMPANION_PREAUTH_SECRET` to be the same on each instance.
* All other configuration needs to be the same, except if youre running many
instances on the same machine, then `COMPANION_PORT` should be different for
each instance.
## API
### Options
:::tip
The headings display the JS and environment variable options (`option`
`ENV_OPTION`). When integrating Companion into your own server, you pass the
options to `companion.app()`. If you are using the standalone version, you
configure Companion using environment variables. Some options only exist as
environment variables or only as a JS option.
:::
<details>
<summary>Default configuration</summary>
```javascript
const options = {
server: {
protocol: 'http',
path: '',
},
providerOptions: {},
s3: {
endpoint: 'https://{service}.{region}.amazonaws.com',
conditions: [],
useAccelerateEndpoint: false,
getKey: (req, filename) => `${crypto.randomUUID()}-${filename}`,
expires: 800, // seconds
},
allowLocalUrls: false,
logClientVersion: true,
periodicPingUrls: [],
streamingUpload: false,
clientSocketConnectTimeout: 60000,
metrics: true,
};
```
</details>
#### `filePath` `COMPANION_DATADIR`
Full path to the directory to which provider files will be downloaded
temporarily.
#### `secret` `COMPANION_SECRET` `COMPANION_SECRET_FILE`
A secret string which Companion uses to generate authorization tokens. You
should generate a long random string for this. For example:
```js
const crypto = require('node:crypto');
const secret = crypto.randomBytes(64).toString('hex');
```
:::caution
Omitting the `secret` in the standalone version will generate a secret for you,
using the above `crypto` string. But when integrating with Express you must
provide it yourself. This is an essential security measure.
:::
:::note
Using a secret file means passing an absolute path to a file with any extension,
which has only the secret, nothing else.
:::
#### `preAuthSecret` `COMPANION_PREAUTH_SECRET` `COMPANION_PREAUTH_SECRET_FILE`
If you are using the [Transloadit](/docs/transloadit) `companionKeysParams`
feature (Transloadit-hosted Companion using your own custom OAuth credentials),
set this variable to a strong randomly generated secret. See also
`COMPANION_SECRET` (but do not use the same secret!)
:::note
Using a secret file means passing an absolute path to a file with any extension,
which has only the secret, nothing else.
:::
#### `uploadUrls` `COMPANION_UPLOAD_URLS`
An allowlist (array) of strings (exact URLs) or regular expressions. Companion
will only accept uploads to these URLs. This ensures that your Companion
instance is only allowed to upload to your trusted servers and prevents
[SSRF](https://en.wikipedia.org/wiki/Server-side_request_forgery) attacks.
#### `COMPANION_PORT`
The port on which to start the standalone server, defaults to 3020. This is a
standalone-only option.
#### `COMPANION_COOKIE_DOMAIN`
Allows you to customize the domain of the cookies created for Express sessions.
This is a standalone-only option.
#### `COMPANION_HIDE_WELCOME`
Setting this to `true` disables the welcome message shown at `/`. This is a
standalone-only option.
#### `redisUrl` `COMPANION_REDIS_URL`
URL to running Redis server. This can be used to scale Companion horizontally
using many instances. See [How to scale Companion](#how-to-scale-companion).
#### `COMPANION_REDIS_EXPRESS_SESSION_PREFIX`
Set a custom prefix for redis keys created by
[connect-redis](https://github.com/tj/connect-redis). Defaults to `sess:`.
Sessions are used for storing authentication state and for allowing thumbnails
to be loaded by the browser via Companion. You might want to change this because
if you run a redis with many different apps in the same redis server, its hard
to know where `sess:` comes from and it might collide with other apps. **Note:**
in the future, we plan and changing the default to `companion:` and possibly
remove this option. This is a standalone-only option. See also
`COMPANION_REDIS_PUBSUB_SCOPE`.
#### `redisOptions`
An object of
[options supported by redis client](https://www.npmjs.com/package/redis#options-object-properties).
This option can be used in place of `redisUrl`.
#### `redisPubSubScope` `COMPANION_REDIS_PUBSUB_SCOPE`
Use a scope for the companion events at the Redis server. Setting this option
will prefix all events with the name provided and a colon. See also
`COMPANION_REDIS_EXPRESS_SESSION_PREFIX`.
#### `server`
Configuration options for the underlying server.
| Key / Environment variable | Value | Description |
| ---------------------------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `protocol` `COMPANION_PROTOCOL` | `http` or `https` | Used to build a URL to reference the Companion instance itself, which is used for headers and cookies. Companion itself always runs as a HTTP server, so locally you should use `http`. You must to set this to `https` once you enabled SSL/HTTPS for your domain in production by running a reverse https-proxy in front of Companion, or with a built-in HTTPS feature of your hosting service. |
| `host` `COMPANION_DOMAIN` | `String` | Your servers publicly facing hostname (for example `example.com`). |
| `oauthDomain` `COMPANION_OAUTH_DOMAIN` | `String` | If you have several instances of Companion with different (and perhaps dynamic) subdomains, you can set a single fixed subdomain and server (such as `sub1.example.com`) to handle your OAuth authentication for you. This would then redirect back to the correct instance with the required credentials on completion. This way you only need to configure a single callback URL for OAuth providers. |
| `path` `COMPANION_PATH` | `String` | The server path to where the Companion app is sitting. For instance, if Companion is at `example.com/companion`, then the path would be `/companion`). |
| `implicitPath` `COMPANION_IMPLICIT_PATH` | `String` | If the URLs path in your reverse proxy is different from your Companion path in your express app, then you need to set this path as `implicitPath`. For instance, if your Companion URL is `example.com/mypath/companion`. Where the path `/mypath` is defined in your NGINX server, while `/companion` is set in your express app. Then you need to set the option `implicitPath` to `/mypath`, and set the `path` option to `/companion`. |
| `validHosts` `COMPANION_DOMAINS` | `Array` | If you are setting an `oauthDomain`, you need to set a list of valid hosts, so the oauth handler can validate the host of the Uppy instance requesting the authentication. This is essentially a list of valid domains running your Companion instances. The list may also contain regex patterns. e.g `['sub2.example.com', 'sub3.example.com', '(\\w+).example.com']` |
#### `sendSelfEndpoint` `COMPANION_SELF_ENDPOINT`
This is essentially the same as the `server.host + server.path` attributes. The
major reason for this attribute is that, when set, it adds the value as the
`i-am` header of every request response.
#### `providerOptions`
Object to enable providers with their keys and secrets. For example:
```json
{
"drive": {
"key": "***",
"secret": "***"
}
}
```
When using the standalone version you use the corresponding environment
variables or point to a secret file (such as `COMPANION_GOOGLE_SECRET_FILE`).
:::note
Secret files need an absolute path to a file with any extension which only has
the secret, nothing else.
:::
| Service | Key | Environment variables |
| ------------ | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Box | `box` | `COMPANION_BOX_KEY`, `COMPANION_BOX_SECRET`, `COMPANION_BOX_SECRET_FILE` |
| Dropbox | `dropbox` | `COMPANION_DROPBOX_KEY`, `COMPANION_DROPBOX_SECRET`, `COMPANION_DROPBOX_SECRET_FILE` |
| Facebook | `facebook` | `COMPANION_FACEBOOK_KEY`, `COMPANION_FACEBOOK_SECRET`, `COMPANION_FACEBOOK_SECRET_FILE` |
| Google Drive | `drive` | `COMPANION_GOOGLE_KEY`, `COMPANION_GOOGLE_SECRET`, `COMPANION_GOOGLE_SECRET_FILE` |
| Instagram | `instagram` | `COMPANION_INSTAGRAM_KEY`, `COMPANION_INSTAGRAM_SECRET`, `COMPANION_INSTAGRAM_SECRET_FILE` |
| OneDrive | `onedrive` | `COMPANION_ONEDRIVE_KEY`, `COMPANION_ONEDRIVE_SECRET`, `COMPANION_ONEDRIVE_SECRET_FILE`, `COMPANION_ONEDRIVE_DOMAIN_VALIDATION` (Settings this variable to `true` enables a route that can be used to validate your app with OneDrive) |
| Zoom | `zoom` | `COMPANION_ZOOM_KEY`, `COMPANION_ZOOM_SECRET`, `COMPANION_ZOOM_SECRET_FILE`, `COMPANION_ZOOM_VERIFICATION_TOKEN` |
#### `s3`
Companion comes with signature endpoints for AWS S3. These can be used by the
Uppy client to sign requests to upload files directly to S3, without exposing
secret S3 keys in the browser. Companion also supports uploading files from
providers like Dropbox and Instagram directly into S3.
##### `s3.key` `COMPANION_AWS_KEY`
The S3 access key ID.
##### `s3.secret` `COMPANION_AWS_SECRET` `COMPANION_AWS_SECRET_FILE`
The S3 secret access key.
:::note
Using a secret file means passing an absolute path to a file with any extension,
which has only the secret, nothing else.
:::
##### `s3.endpoint` `COMPANION_AWS_ENDPOINT`
Optional URL to a custom S3 (compatible) service. Otherwise uses the default
from the AWS SDK.
##### `s3.bucket` `COMPANION_AWS_BUCKET`
The name of the bucket to store uploaded files in.
It can be function that returns the name of the bucket as a `string` and takes
the following arguments:
* [`http.IncomingMessage`][], the HTTP request (will be `null` for remote
uploads)
* metadata provided by the user for the file (will be `undefined` for local
uploads)
##### `s3.region` `COMPANION_AWS_REGION`
The datacenter region where the target bucket is located.
##### `COMPANION_AWS_PREFIX`
An optional prefix for all uploaded keys. This is a standalone-only option. The
same can be achieved by the `getKey` option when using the express middleware.
##### `s3.awsClientOptions`
You can supply any
[S3 option supported by the AWS SDK](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property)
in the `providerOptions.s3.awsClientOptions` object, _except for_ the below:
* `accessKeyId`. Instead, use the `providerOptions.s3.key` property. This is to
make configuration names consistent between different Companion features.
* `secretAccessKey`. Instead, use the `providerOptions.s3.secret` property. This
is to make configuration names consistent between different Companion
features.
Be aware that some options may cause wrong behaviour if they conflict with
Companions assumptions. If you find that a particular option does not work as
expected, please
[open an issue on the Uppy repository](https://github.com/transloadit/uppy/issues/new)
so we can document it here.
##### `s3.getKey(req, filename, metadata)`
Get the key name for a file. The key is the file path to which the file will be
uploaded in your bucket. This option should be a function receiving three
arguments:
* `req` [`http.IncomingMessage`][], the HTTP request, for _regular_ S3 uploads
using the `@uppy/aws-s3` plugin. This parameter is _not_ available for
multipart uploads using the `@uppy/aws-s3` or `@uppy/aws-s3-multipart`
plugins. This parameter is `null` for remote uploads.
* `filename`, the original name of the uploaded file;
* `metadata`, user-provided metadata for the file.
This function should return a string `key`. The `req` parameter can be used to
upload to a user-specific folder in your bucket, for example:
```js
app.use(authenticationMiddleware);
app.use(
uppy.app({
providerOptions: {
s3: {
getKey: (req, filename, metadata) => `${req.user.id}/${filename}`,
/* auth options */
},
},
}),
);
```
The default implementation returns the `filename`, so all files will be uploaded
to the root of the bucket as their original file name.
```js
app.use(
uppy.app({
providerOptions: {
s3: {
getKey: (req, filename, metadata) => filename,
},
},
}),
);
```
When signing on the client, this function will only be called for multipart
uploads.
#### `COMPANION_AWS_USE_ACCELERATE_ENDPOINT`
Enable S3
[Transfer Acceleration](https://docs.aws.amazon.com/AmazonS3/latest/userguide/transfer-acceleration.html).
This is a standalone-only option.
#### `COMPANION_AWS_EXPIRES`
Set `X-Amz-Expires` query parameter in the presigned urls (in seconds, default:
300\). This is a standalone-only option.
#### `COMPANION_AWS_ACL`
Set a
[Canned ACL](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl)
for uploaded objects. This is a standalone-only option.
#### `customProviders`
This option enables you to add custom providers along with the already supported
providers. See [adding custom providers](#how-to-add-custom-providers) for more
information.
#### `logClientVersion`
A boolean flag to tell Companion whether to log its version upon startup.
#### `metrics` `COMPANION_HIDE_METRICS`
A boolean flag to tell Companion whether to provide an endpoint `/metrics` with
Prometheus metrics (by default metrics are enabled.)
#### `streamingUpload` `COMPANION_STREAMING_UPLOAD`
A boolean flag to tell Companion whether to enable streaming uploads. If
enabled, it will lead to _faster uploads_ because companion will start uploading
at the same time as downloading using `stream.pipe`. If `false`, files will be
fully downloaded first, then uploaded. Defaults to `false`, but we recommended
enabling it, especially if youre expecting to upload large files. In future
versions the default might change to `true`.
#### `maxFileSize` `COMPANION_MAX_FILE_SIZE`
If this value is set, companion will limit the maximum file size to process. If
unset, it will process files without any size limit (this is the default).
#### `periodicPingUrls` `COMPANION_PERIODIC_PING_URLS`
If this value is set, companion will periodically send POST requests to the
specified URLs. Useful for keeping track of companion instances as a keep-alive.
#### `periodicPingInterval` `COMPANION_PERIODIC_PING_INTERVAL`
Interval for periodic ping requests (in ms).
#### `periodicPingStaticPayload` `COMPANION_PERIODIC_PING_STATIC_JSON_PAYLOAD`
A `JSON.stringify`-able JavaScript Object that will be sent as part of the JSON
body in the period ping requests.
#### `allowLocalUrls` `COMPANION_ALLOW_LOCAL_URLS`
A boolean flag to tell Companion whether to allow requesting local URLs
(non-internet IPs).
:::caution
Only enable this in development. **Enabling it in production is a security
risk.**
:::
#### `corsOrigins` `COMPANION_CLIENT_ORIGINS`
Allowed CORS Origins (default `true`). Passed as the `origin` option in
[cors](https://github.com/expressjs/cors#configuration-options))
#### `COMPANION_CLIENT_ORIGINS_REGEX`
Like COMPANION\_CLIENT\_ORIGINS, but allows a single regex instead.
`COMPANION_CLIENT_ORIGINS` will be ignored if this is used. This is a
standalone-only option.
#### `chunkSize` `COMPANION_CHUNK_SIZE`
Controls how big the uploaded chunks are for AWS S3 Multipart and Tus. Smaller
values lead to more overhead, but larger values lead to slower retries in case
of bad network connections. Passed to tus-js-client
[`chunkSize`](https://github.com/tus/tus-js-client/blob/master/docs/api.md#chunksize)
as well as
[AWS S3 Multipart](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html)
`partSize`.
#### `enableUrlEndpoint` `COMPANION_ENABLE_URL_ENDPOINT`
Set this to `false` to disable the
[URL functionalily](https://uppy.io/docs/url/). Default: `true`.
### Events
The object returned by `companion.app()` also has a property `companionEmitter`
which is an `EventEmitter` that emits the following events:
* `upload-start` - When an upload starts, this event is emitted with an object
containing the property `token`, which is a unique ID for the upload.
* **token** - The event name is the token from `upload-start`. The event has an
object with the following properties:
* `action` - One of the following strings:
* `success` - When the upload succeeds.
* `error` - When the upload fails with an error.
* `payload` - the error or success payload.
Example code for using the `EventEmitter` to handle a finished file upload:
```js
const companionApp = companion.app(options);
const { companionEmitter: emitter } = companionApp;
emitter.on('upload-start', ({ token }) => {
console.log('Upload started', token);
function onUploadEvent({ action, payload }) {
if (action === 'success') {
emitter.off(token, onUploadEvent); // avoid listener leak
console.log('Upload finished', token, payload.url);
} else if (action === 'error') {
emitter.off(token, onUploadEvent); // avoid listener leak
console.error('Upload failed', payload);
}
}
emitter.on(token, onUploadEvent);
});
```
<!--retext-simplify ignore frequently-->
## Frequently asked questions
### Do you have a live example?
An example server is running at <https://companion.uppy.io>.
### How does the Authentication and Token mechanism work?
This section describes how Authentication works between Companion and Providers.
While this behaviour is the same for all Providers (Dropbox, Instagram, Google
Drive, etc.), we are going to be referring to Dropbox in place of any Provider
throughout this section.
The following steps describe the actions that take place when a user
Authenticates and Uploads from Dropbox through Companion:
* The visitor to a website with Uppy clicks `Connect to Dropbox`.
* Uppy sends a request to Companion, which in turn sends an OAuth request to
Dropbox (Requires that OAuth credentials from Dropbox have been added to
Companion).
* Dropbox asks the visitor to log in, and whether the Website should be allowed
to access your files
* If the visitor agrees, Companion will receive a token from Dropbox, with which
we can temporarily download files.
* Companion encrypts the token with a secret key and sends the encrypted token
to Uppy (client)
* Every time the visitor clicks on a folder in Uppy, it asks Companion for the
new list of files, with this question, the token (still encrypted by
Companion) is sent along.
* Companion decrypts the token, requests the list of files from Dropbox and
sends it to Uppy.
* When a file is selected for upload, Companion receives the token again
according to this procedure, decrypts it again, and thereby downloads the file
from Dropbox.
* As the bytes arrive, Companion uploads the bytes to the final destination
(depending on the configuration: Apache, a Tus server, S3 bucket, etc).
* Companion reports progress to Uppy, as if it were a local upload.
* Completed!
### How to use provider redirect URIs?
When generating your provider API keys on their corresponding developer
platforms (e.g
[Google Developer Console](https://console.developers.google.com/)), youd need
to provide a `redirect URI` for the OAuth authorization process. In general the
redirect URI for each provider takes the format:
`http(s)://$YOUR_COMPANION_HOST_NAME/$PROVIDER_NAME/redirect`
For example, if your Companion server is hosted on
`https://my.companion.server.com`, then the redirect URI you would supply for
your OneDrive provider would be:
`https://my.companion.server.com/onedrive/redirect`
Please see
[Supported Providers](https://uppy.io/docs/companion/#Supported-providers) for a
list of all Providers and their corresponding names.
### How to use Companion with Kubernetes?
We have a detailed
[guide](https://github.com/transloadit/uppy/blob/main/packages/%40uppy/companion/KUBERNETES.md)
on running Companion in Kubernetes.
### How to add custom providers?
As of now, Companion supports the
[providers listed here](https://uppy.io/docs/companion/#Supported-providers) out
of the box, but you may also choose to add your own custom providers. You can do
this by passing the `customProviders` option when calling the Uppy `app` method.
The custom provider is expected to support Oauth 1 or 2 for
authentication/authorization.
```javascript
import providerModule from './path/to/provider/module';
const options = {
customProviders: {
myprovidername: {
config: {
authorize_url: 'https://mywebsite.com/authorize',
access_url: 'https://mywebsite.com/token',
oauth: 2,
key: '***',
secret: '***',
scope: ['read', 'write'],
},
module: providerModule,
},
},
};
uppy.app(options);
```
The `customProviders` option should be an object containing each custom
provider. Each custom provider would, in turn, be an object with two keys,
`config` and `module`. The `config` option would contain Oauth API settings,
while the `module` would point to the provider module.
To work well with Companion, the **module** must be a class with the following
methods. Note that the methods must be `async`, return a `Promise` or reject
with an `Error`):
1. `async list ({ token, directory, query })` - Returns a object containing a
list of user files (such as a list of all the files in a particular
directory). See [example returned list data structure](#list-data). `token` -
authorization token (retrieved from oauth process) to send along with your
request
* `directory` - the id/name of the directory from which data is to be
retrieved. This may be ignored if it doesnt apply to your provider
* `query` - expressjs query params object received by the server (in case
some data you need in there).
2. `async download ({ token, id, query })` - Downloads a particular file from
the provider. Returns an object with a single property `{ stream }` - a
[`stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable),
which will be read from and uploaded to the destination. To prevent memory
leaks, make sure you release your stream if you reject this method with an
error.
* `token` - authorization token (retrieved from oauth process) to send along
with your request.
* `id` - ID of the file being downloaded.
* `query` - expressjs query params object received by the server (in case
some data you need in there).
3. `async size ({ token, id, query })` - Returns the byte size of the file that
needs to be downloaded as a `Number`. If the size of the object is not known,
`null` may be returned.
* `token` - authorization token (retrieved from oauth process) to send along
with your request.
* `id` - ID of the file being downloaded.
* `query` - expressjs query params object received by the server (in case
some data you need in there).
The class must also have:
* A unique `static authProvider` string property - a lowercased value which
indicates name of the [`grant`](https://github.com/simov/grant) OAuth2
provider to use (e.g `google` for Google). If your provider doesnt use
OAuth2, you can omit this property.
* A `static` property `static version = 2`, which is the current version of the
Companion Provider API.
See also
[example code with a custom provider](https://github.com/transloadit/uppy/blob/main/examples/custom-provider/server).
#### list data
```json
{
// username or email of the user whose provider account is being accessed
"username": "johndoe",
// list of files and folders in the directory. An item is considered a folder
// if it mainly exists as a collection to contain sub-items
"items": [
{
// boolean value of whether or NOT it's a folder
"isFolder": false,
// icon image URL
"icon": "https://random-api.url.com/fileicon.jpg",
// name of the item
"name": "myfile.jpg",
// the mime type of the item. Only relevant if the item is NOT a folder
"mimeType": "image/jpg",
// the id (in string) of the item
"id": "uniqueitemid",
// thumbnail image URL. Only relevant if the item is NOT a folder
"thumbnail": "https://random-api.url.com/filethumbnail.jpg",
// for folders this is typically the value that will be passed as "directory" in the list(...) method.
// For files, this is the value that will be passed as id in the download(...) method.
"requestPath": "file-or-folder-requestpath",
// datetime string (in ISO 8601 format) of when this item was last modified
"modifiedDate": "2020-06-29T19:59:58Z",
// the size in bytes of the item. Only relevant if the item is NOT a folder
"size": 278940,
"custom": {
// an object that may contain some more custom fields that you may need to send to the client. Only add this object if you have a need for it.
"customData1": "the value",
"customData2": "the value"
}
// more items here
}
],
// if the "items" list is paginated, this is the request path needed to fetch the next page.
"nextPagePath": "directory-name?cursor=cursor-to-next-page"
}
```
### How to run Companion locally?
1. To set up Companion for local development, please clone the Uppy repo and
install, like so:
```bash
git clone https://github.com/transloadit/uppy
cd uppy
yarn install
```
2. Configure your environment variables by copying the `env.example.sh` file to
`env.sh` and edit it to its correct values.
```bash
cp .env.example .env
$EDITOR .env
```
3. To start the server, run:
```bash
yarn run start:companion
```
This would get the Companion instance running on `http://localhost:3020`. It
uses [nodemon](https://github.com/remy/nodemon) so it will automatically restart
when files are changed.
[`http.incomingmessage`]: https://nodejs.org/api/http.html#class-httpincomingmessage
[box]: /docs/box
[dropbox]: /docs/dropbox
[facebook]: /docs/facebook
[googledrive]: /docs/google-drive
[instagram]: /docs/instagram
[onedrive]: /docs/onedrive
[unsplash]: /docs/unsplash
[url]: /docs/url
[zoom]: /docs/zoom
[transloadit]: https://transloadit.com

125
docs/compressor.mdx Normal file
View file

@ -0,0 +1,125 @@
---
sidebar_position: 12
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Compressor
The `@uppy/compressor` plugin optimizes images (JPEG, PNG, and any other format
supported by the clients browser) before upload, saving up to 60% in size
(roughly 18 MB for 10 images). It uses [Compressor.js][] library under the hood.
## When should I use it?
When your users are likely to upload images, potentially on mobile devices, and
saving data and faster uploads are important.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/compressor
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/compressor
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Compressor } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(Compressor, {
// Options
})
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
```js {7} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import Compressor from '@uppy/compressor';
new Uppy()
.use(Dashboard, {inline:true, target: '#dashboard')
.use(Compressor);
```
No action is needed from the user — Uppy will automatically optimize images,
show an [Informer](/docs/informer) message with saved bytes, and then begin the
upload as usual.
## API
### Options
:::tip
You can also pass any of the [Compressor.js options][] here as well.
:::
#### `id`
A unique identifier for this plugin (`string`, default: `'Compressor'`).
#### `quality`
The quality of the output image passed to [Compressor.js][] (`number`, default:
`0.6`).
It must be a number between `0` and `1`. Be careful to use `1` as it may make
the size of the output image become larger. In most cases, going with the
default value is best.
:::note
This option is only available for `image/jpeg` and `image/webp` images.
:::
#### `limit`
Number of images that will be compressed in parallel (`number`, default: `10`).
You likely dont need to change this, unless you are experiencing performance
issues.
#### `locale`
```js
export default {
strings: {
// Shown in the Status Bar
compressingImages: 'Compressing images...',
compressedX: 'Saved %{size} by compressing images',
},
};
```
## Events
#### `compressor:complete`
The event is emitted when all files are compressed. You can use it for side
effects or custom UI notifications.
[compressor.js]: https://github.com/fengyuanchen/compressorjs
[compressor.js options]: https://github.com/fengyuanchen/compressorjs#options

181
docs/form.mdx Normal file
View file

@ -0,0 +1,181 @@
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Form
The `@uppy/form` plugin integrates with an existing HTML `<form>` element to
extract input data from it, and send along with the Uppy upload. It then appends
the upload result back to the form via a hidden input.
## When should I use this?
When you have an existing HTML `<form>` element and you would like to:
- **Attach the form input values to the files.** This is useful if you want to
associate meta data from the form (for example, name, location, id) with the
uploaded file, so you can process it on the backend. `@uppy/form` extracts the
input values before uploading/processing files and adds them to Uppy meta data
state (`uppy.state.meta`), as well as and each files meta, and appends to the
upload in an object with `[file input name attribute]` -> `[file input value]`
key/values.
- **Upload the files and put the response (such as the file URLs) into a hidden
field** (`<input type="hidden" name="uppyResult">`). Then you can POST and
handle the form yourself. The appended result is a stringified version of a
result returned from calling `uppy.upload()` or listening to `complete` event.
- **Automatically start the file upload on submit or submit the form after file
upload.** This is off by default. See [`submitOnSuccess`](#submitOnSuccess)
and [`triggerUploadOnSubmit`](#triggerUploadOnSubmit) options respectively for
details.
:::note
If you are using a UI framework or library like React, Vue or Svelte, youll
most likely handle form data there as well, and thus wont need this plugin.
Instead, pass meta data to Uppy via [`uppy.setMeta()`](/docs/uppy#setmetadata)
and listen to [`uppy.on('complete')`](/docs/uppy#complete) to get the upload
results back.
:::
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/form
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/form
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Form } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(Form, {
// Options
})
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
```js title="app.js"
import Uppy from '@uppy/core';
import Form from '@uppy/form';
import DragDrop from '@uppy/drag-drop';
import '@uppy/core/dist/style.min.css';
import '@uppy/drag-drop/dist/style.min.css';
new Uppy().use(Form, {
target: '#my-form',
});
```
```html title="index.html"
<form id="my-form" action="/submit" method="get">
<label for="name">Enter your name: </label>
<input type="text" name="name" required />
<label for="dob">Date of birth: </label>
<input type="date" name="dob" />
<input type="submit" value="Save" />
</form>
```
By default the code above will:
1. Extract meta data from the form `#my-form`.
2. Send it with the Uppy upload.
3. Those fields will then be added to Uppy meta data state (`uppy.state.meta`)
and each files meta, and appended as (meta)data to the upload in an object
with `[file input name attribute]` -> `[file input value]` key/values.
4. When Uppy completes upload/processing, it will add an
`<input type="hidden" name="uppyResult">` with the stringified upload result
object back to the form.
:::note
You can disable both of these features, see options below.
:::
:::tip
`@uppy/form` can also start Uppy upload automatically once the form is
submitted, and even submit the form after the upload is complete. This is off by
default. See [`triggerUploadOnSubmit`](#triggerUploadOnSubmit) and
[`submitOnSuccess`](#submitOnSuccess) options below for details.
:::
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'Form'`).
#### `target`
DOM element or CSS selector for the form element (`string` or `Element`,
default: `null`).
This is required for the plugin to work.
#### `resultName`
The `name` attribute for the `<input type="hidden">` where the result will be
added (`string`, default: `uppyResult`).
#### `getMetaFromForm`
Configures whether to extract metadata from the form (`boolean`, default:
`true`).
When set to `true`, the Form plugin will extract all fields from a `<form>`
element before upload begins. Those fields will then be added to Uppy meta data
state (`uppy.state.meta`) and each files meta, and appended as (meta)data to
the upload in an object with `[file input name attribute]` ->
`[file input value]` key/values.
#### `addResultToForm`
Configures whether to add upload/encoding results back to the form in an
`<input name="uppyResult" type="hidden">` element (`boolean`, default: `true`).
#### `triggerUploadOnSubmit`
Configures whether to start the upload when the form is submitted (`boolean`,
default: `false`).
When a user submits the form (via a submit button, the <kbd>Enter</kbd> key or
otherwise), this option will prevent form submission, and instead upload files
via Uppy. Then you could:
- Set `submitOnSuccess: true` if you need the form to _actually_ be submitted
once all files have been uploaded.
- Listen for `uppy.on('complete')` event to do something else if the file
uploads are all you need. For example, if the form is used for file metadata
only.
#### `submitOnSuccess`
Configures whether to submit the form after Uppy finishes uploading/encoding
(`boolean`, default: `false`).

View file

@ -0,0 +1,4 @@
{
"label": "Framework integrations",
"position": 8
}

View file

@ -0,0 +1,108 @@
---
slug: /angular
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
# Angular
[Angular][] components for Uppy UI plugins.
## When should I use it?
When you are using the Angular framework and you wouldl like to use on of the UI
components.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/angular
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/angular
```
</TabItem>
</Tabs>
:::note
You also need to install the UI plugin you want to use. For instance,
`@uppy/dashboard`.
:::
## Use
Instead of adding a UI plugin to an Uppy instance with `.use()`, the Uppy
instance can be passed into components as a `props` prop.
The following plugins are available as Angular component wrappers:
- `<uppy-dashboard />` renders [`@uppy/dashboard`](/docs/dashboard)
- `<uppy-drag-drop />` renders [`@uppy/drag-drop`](/docs/drag-drop)
- `<uppy-progress-bar />` renders [`@uppy/progress-bar`](/docs/progress-bar)
- `<uppy-status-bar />` renders [`@uppy/status-bar`](/docs/status-bar)
Each component takes a `props` prop that will be passed to the UI Plugin.
```typescript title="app.module.ts" showLineNumbers
import { NgModule } from '@angular/core';
import { UppyAngularDashboardModule } from '@uppy/angular';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, UppyAngularDashboardModule],
providers: [],
bootstrap: [AppComponent],
})
class {}
```
```html title="app.component.html" showLineNumbers
<uppy-dashboard [uppy]="uppy"> </uppy-dashboard>
```
You should initialize Uppy as a property of your component.
```typescript title="app.component.ts" showLineNumbers
import { Component } from '@angular/core';
import { Uppy } from '@uppy/core';
@Component({
selector: 'app-root',
})
export class AppComponent {
uppy: Uppy = new Uppy({ debug: true, autoProceed: true });
}
```
### CSS
All components have their own styling and should be added to your component
decorator. You can find the CSS import statements in the docs of the UI plugin
you want to use. For instance, for `@uppy/dashboard`:
```typescript
@Component({
// ...
styleUrls: [
'../node_modules/@uppy/core/dist/style.css',
'../node_modules/@uppy/dashboard/dist/style.css',
],
})
```
[angular]: https://angular.io

View file

@ -0,0 +1,228 @@
---
slug: /react
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
# React
[React][] components for the Uppy UI plugins and a `useUppyState` hook.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/react
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/react
```
</TabItem>
</Tabs>
:::note
You also need to install the UI plugin you want to use. For instance,
`@uppy/dashboard`.
:::
## Use
`@uppy/react` exposes component wrappers for `Dashboard`, `DragDrop`, and all
other UI elements. The components can be used with either [React][] or
API-compatible alternatives such as [Preact][].
:::caution
If you find yourself writing many instances of `useState` and `useEffect` to
achieve something with Uppy in React, you are most likely breaking React best
practices. Consider reading
“[You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect)”
and looking at our examples below.
:::
### Components
The following components are exported from `@uppy/react`:
- `<Dashboard />` renders [`@uppy/dashboard`](/docs/dashboard)
- `<DragDrop />` renders [`@uppy/drag-drop`](/docs/drag-drop)
- `<ProgressBar />` renders [`@uppy/progress-bar`](/docs/progress-bar)
- `<StatusBar />` renders [`@uppy/status-bar`](/docs/status-bar)
{/* prettier-ignore */}
{/* Commented out until the hook is live
### Hooks
`useUppyState(uppy, selector)`
Use this hook when you need to access Uppys state reactively. Most of the
times, this is needed if you are building a custom UI for Uppy in React.
```js
// IMPORTANT: passing an initializer function to prevent Uppy from being reinstantiated on every render.
const [uppy] = useState(() => new Uppy());
const files = useUppyState(uppy, (state) => state.files);
const totalProgress = useUppyState(uppy, (state) => state.totalProgress);
// We can also get specific plugin state.
// Note that the value on `plugins` depends on the `id` of the plugin.
const metaFields = useUppyState(
uppy,
(state) => state.plugins?.Dashboard?.metaFields,
);
```
You can see all the values you can access on the
[`State`](https://github.com/transloadit/uppy/blob/main/packages/%40uppy/core/types/index.d.ts#L190)
type. If you are accessing plugin state, you would have to look at the types of
the plugin.
\*/}
## Examples
### Example: basic component
Here we have a basic component which ties Uppys state to the component. This
means you can render multiple instances. But be aware that as your component
unmounts, for instance because the user navigates to a different page, Uppys
state will be lost and uploads will stop.
:::note
If you render multiple instances of Uppy, make sure to give each instance a
unique `id`.
:::
```js
import React, { useEffect, useState } from 'react';
import Uppy from '@uppy/core';
import Webcam from '@uppy/webcam';
import { Dashboard } from '@uppy/react';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
import '@uppy/webcam/dist/style.min.css';
function Component() {
// IMPORTANT: passing an initializer function to prevent Uppy from being reinstantiated on every render.
const [uppy] = useState(() => new Uppy().use(Webcam));
return <Dashboard uppy={uppy} plugins={['Webcam']} />;
}
```
### Example: keep Uppy state and uploads while navigating between pages
When you want Uppys state to persist and keep uploads running between pages,
you can
[lift the state up](https://react.dev/learn/sharing-state-between-components#lifting-state-up-by-example).
```js
import React, { useState, useEffect } from 'react';
import Uppy from '@uppy/core';
import { Dashboard } from '@uppy/react';
function Page1() {
// ...
}
function Page2({ uppy }) {
return (
<>
<p>{totalProgress}</p>
<Dashboard id="dashboard" uppy={uppy} />
</>
);
}
export default function App() {
// keeping the uppy instance alive above the pages the user can switch during uploading
const [uppy] = useState(() => new Uppy());
return (
// Add your router here
<>
<Page1 />
<Page2 uppy={uppy} />
</>
);
}
```
### Example: updating Uppys options dynamically based on props
```js
// ...
function Component(props) {
// IMPORTANT: passing an initializer function to prevent the state from recreating.
const [uppy] = useState(() => new Uppy().use(Webcam));
useEffect(() => {
uppy.setOptions({ restrictions: props.restrictions });
}, [props.restrictions]);
useEffect(() => {
uppy.getPlugin('Webcam').setOptions({ modes: props.webcamModes });
}, [props.webcamModes]);
return <Dashboard uppy={uppy} plugins={['Webcam']} />;
}
```
### Example: dynamic params and signature for Transloadit
When you go to production always make sure to set the `signature`. **Not using
[Signature Authentication](https://transloadit.com/docs/topics/signature-authentication/)
can be a security risk**. Signature Authentication is a security measure that
can prevent outsiders from tampering with your Assembly Instructions.
Generating a signature should be done on the server to avoid leaking secrets. In
React, this could get awkward with a `fetch` in a `useEffect` and setting it to
`useState`. Instead, its easier to use the
[`assemblyOptions`](/docs/transloadit#assemblyoptions) option to `fetch` the
params.
```js
// ...
function createUppy(userId) {
return new Uppy({ meta: { userId } }).use(Transloadit, {
async assemblyOptions(file) {
// You can send meta data along for use in your template.
// https://transloadit.com/docs/topics/assembly-instructions/#form-fields-in-instructions
const body = JSON.stringify({ userId: file.meta.userId });
const res = await fetch('/transloadit-params', { method: 'POST', body });
return response.json();
},
});
}
function Component({ userId }) {
// IMPORTANT: passing an initializer function to prevent Uppy from being reinstantiated on every render.
const [uppy] = useState(() => createUppy(userId));
useEffect(() => {
if (userId) {
// Adding to global `meta` will add it to every file.
uppy.setOptions({ meta: { userId } });
}
}, [uppy, userId]);
}
```
[react]: https://facebook.github.io/react
[preact]: https://preactjs.com/

View file

@ -0,0 +1,70 @@
---
slug: /svelte
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
# Svelte
[Svelte][] components for the Uppy UI plugins.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/svelte
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/svelte
```
</TabItem>
</Tabs>
:::note
You also need to install the UI plugin you want to use. For instance,
`@uppy/dashboard`.
:::
## Use
The following plugins are available as Svelte component wrappers:
- `<Dashboard />` renders [`@uppy/dashboard`](/docs/dashboard)
- `<DragDrop />` renders [`@uppy/drag-drop`](/docs/drag-drop)
- `<ProgressBar />` renders [`@uppy/progress-bar`](/docs/progress-bar)
- `<StatusBar />` renders [`@uppy/status-bar`](/docs/status-bar)
Instead of adding a UI plugin to an Uppy instance with `.use()`, the Uppy
instance can be passed into components as an `uppy` prop. Due to the way Svelte
handles reactivity, you can initialize Uppy the same way you would with vanilla
JavaScript.
```html
<script>
import { Dashboard } from '@uppy/svelte';
import Uppy from '@uppy/core';
import Webcam from '@uppy/webcam';
// Don't forget the CSS: core and UI components + plugins you are using
import '@uppy/core/dist/style.css';
import '@uppy/dashboard/dist/style.css';
import '@uppy/webcam/dist/style.css';
const uppy = new Uppy().use(Webcam);
</script>
<main><Dashboard uppy={uppy} plugins={["Webcam"]} /></main>
```
[svelte]: https://svelte.dev

View file

@ -0,0 +1,73 @@
---
slug: /vue
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
# Vue
[Vue][] components for the Uppy UI plugins.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/vue
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/vue
```
</TabItem>
</Tabs>
:::note
You also need to install the UI plugin you want to use. For instance,
`@uppy/dashboard`.
:::
## Use
The following plugins are available as Vue component wrappers:
- `<Dashboard />` renders [`@uppy/dashboard`](/docs/dashboard) inline
- `<DashboardModal />` renders [`@uppy/dashboard`](/docs/dashboard) as a modal
- `<DragDrop />` renders [`@uppy/drag-drop`](/docs/drag-drop)
- `<ProgressBar />` renders [`@uppy/progress-bar`](/docs/progress-bar)
- `<StatusBar />` renders [`@uppy/status-bar`](/docs/status-bar)
Instead of adding a UI plugin to an Uppy instance with `.use()`, the Uppy
instance can be passed into components as an `uppy` prop. Due to the way Vue
handles reactivity, you can initialize Uppy the same way you would with vanilla
JavaScript.
```html
<script>
import { Dashboard } from '@uppy/vue';
import Uppy from '@uppy/core';
import Webcam from '@uppy/webcam';
// Don't forget the CSS: core and UI components + plugins you are using
import '@uppy/core/dist/style.css';
import '@uppy/dashboard/dist/style.css';
import '@uppy/webcam/dist/style.css';
const uppy = new Uppy().use(Webcam);
</script>
<template>
<Dashboard :uppy="uppy" :plugins="['Webcam']" />
</template>
```
[vue]: https://vuejs.org

150
docs/golden-retriever.mdx Normal file
View file

@ -0,0 +1,150 @@
---
sidebar_position: 11
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Golden Retriever
The `@uppy/golden-retriever` plugin saves selected files in your browser cache,
so that if the browser crashes, or the user accidentally closes the tab, Uppy
can restore everything and continue uploading as if nothing happened. You can
read more about it
[on our blog](https://uppy.io/blog/2017/07/golden-retriever/).
The Golden Retriever uses three methods of browser data storage:
- `LocalStorage` to store file metadata and Uppy state only.
- `IndexedDB` for small files, usually under 5MiB.
- `Service Worker` (_optional_) for _all_ files because, unlike `IndexedDB`,
`Service Worker` can keep references to large files. Service Worker storage is
_quite_ temporary though, and doesnt persist across browser crashes or
restarts. It works well, however, for accidental refreshes or closed tabs.
Upon restore, the plugin first restores state from `LocalStorage` and then
checks both file storages — `IndexedDB` and `ServiceWorker` — merging the
results.
If restore is unsuccessful for certain files, they will be marked as “ghosts” in
the Dashboard UI, and a message + button offering to re-select those files will
be displayed.
Checkout the
[storage quotas](https://developer.mozilla.org/en-US/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria#other_web_technologies)
on MDN to see how much data can be stored depending on the device and browser.
## When should I use this?
When you want extra insurance for the user-selected files. If you feel like
users might spend some time picking files, tweaking descriptions etc, and will
not appreciate having to do it over again if something crashes. Another use case
might be when you think user might want to pick a few files, navigate away to do
something else in your app or otherwise, and then come back to the same
selection.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/golden-retriever
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/golden-retriever
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, GoldenRetriever } from "{{UPPY_JS_URL}}"
new Uppy().use(GoldenRetriever)
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
```js {7} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import GoldenRetriever from '@uppy/golden-retriever';
new Uppy()
.use(Dashboard, {inline:true, target: '#dashboard')
.use(GoldenRetriever);
```
By default, Golden Retriever will only use the `IndexedDB` storage, which is
good enough for files up to 5 MiB. `Service Worker` is optional and requires
setup.
### Enabling Service Worker
With the Service Worker storage, Golden Retriever will be able to temporary
store references to large files.
1. Bundle your own service worker `sw.js` file with Uppy GoldenRetrievers
service worker.
:::tip
For Webpack, check out
[serviceworker-webpack-plugin](https://github.com/oliviertassinari/serviceworker-webpack-plugin).
:::
```js title="sw.js"
import('@uppy/golden-retriever/lib/ServiceWorker');
```
2. Register it in your apps entry point:
```js
// you app.js entry point
uppy.use(GoldenRetriever, { serviceWorker: true });
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/sw.js') // path to your bundled service worker with GoldenRetriever service worker
.then((registration) => {
console.log(
'ServiceWorker registration successful with scope: ',
registration.scope,
);
})
.catch((error) => {
console.log(`Registration failed with ${error}`);
});
}
```
Voilà, thats it. Happy retrieving!
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'GoldenRetriever'`).
#### `expires`
How long to store metadata and files for. Used for `LocalStorage` and
`IndexedDB` (`number`, default: `24 * 60 * 60 * 1000` // 24 hours).
#### `serviceWorker`
Whether to enable `Service Worker` storage (`boolean`, default: `false`).

View file

@ -0,0 +1,4 @@
{
"label": "Guides",
"position": 2
}

View file

@ -0,0 +1,62 @@
---
sidebar_position: 7
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Supporting IE11
We officially support recent versions of Chrome, Firefox, Safari and Edge.
Internet Explorer is not officially supported, as in we dont run tests for it,
but you can be mostly confident it works with the right polyfills. But it does
come with a risk of unexpected results in styling or functionality.
## Polyfills
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install core-js whatwg-fetch abortcontroller-polyfill md-gum-polyfill resize-observer-polyfill
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add core-js whatwg-fetch abortcontroller-polyfill md-gum-polyfill resize-observer-polyfill
```
</TabItem>
</Tabs>
```js
import 'core-js';
import 'whatwg-fetch';
import 'abortcontroller-polyfill/dist/polyfill-patch-fetch';
// Order matters: AbortController needs fetch which needs Promise (provided by core-js).
import 'md-gum-polyfill';
import ResizeObserver from 'resize-observer-polyfill';
window.ResizeObserver ??= ResizeObserver;
export { default } from '@uppy/core';
export * from '@uppy/core';
```
## Legacy CDN bundle
<UppyCdnExample uppyJsName="uppy.legacy.min.js">
{`
import { Uppy, DragDrop, Tus } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(DragDrop, { target: '#uppy' })
uppy.use(Tus, { endpoint: '//tusd.tusdemo.net/files/' })
`}
</UppyCdnExample>

View file

@ -0,0 +1,382 @@
---
sidebar_position: 3
---
# Building plugins
You can find already a few useful Uppy plugins out there, but there might come a
time when you will want to build your own. Plugins can hook into the upload
process or render a custom UI, typically to:
* Render some custom UI element, such as [StatusBar](/docs/status-bar) or
[Dashboard](/docs/dashboard).
* Do the actual uploading, such as [XHRUpload](/docs/xhr-upload) or
[Tus](/docs/tus).
* Do work before the upload, like compressing an image or calling external API.
* Interact with a third-party service to process uploads correctly, such as
[Transloadit](/docs/transloadit) or [AwsS3](/docs/aws-s3).
See a [full example of a plugin](#example-of-a-custom-plugin) below.
## Creating A Plugin
Uppy has two classes to create plugins with. `BasePlugin` for plugins that dont
need a user interface, and `UIPlugin` for ones that do. Each plugin has an `id`
and a `type`. `id`s are used to uniquely identify plugins. A `type` can be
anything—some plugins use `type`s to decide whether to do something to some
other plugin. For example, when targeting plugins at the built-in `Dashboard`
plugin, the Dashboard uses the `type` to figure out where to mount different UI
elements. `'acquirer'`-type plugins are mounted into the tab bar, while
`'progressindicator'`-type plugins are mounted into the progress bar area.
The plugin constructor receives the Uppy instance in the first parameter, and
any options passed to `uppy.use()` in the second parameter.
```js
import BasePlugin from '@uppy/core/lib/BasePlugin.js';
export default class MyPlugin extends BasePlugin {
constructor(uppy, opts) {
super(uppy, opts);
this.id = opts.id || 'MyPlugin';
this.type = 'example';
}
}
```
## Methods
Plugins can define methods to execute certain tasks. The most important method
is `install()`, which is called when a plugin is `.use`d.
All the below methods are optional! Only define the methods you need.
### `BasePlugin`
#### `install()`
Called when the plugin is `.use`d. Do any setup work here, like attaching events
or adding [upload hooks](#Upload-Hooks).
```js
export default class MyPlugin extends UIPlugin {
// ...
install() {
this.uppy.on('upload-progress', this.onProgress);
this.uppy.addPostProcessor(this.afterUpload);
}
}
```
#### `uninstall()`
Called when the plugin is removed, or the Uppy instance is closed. This should
undo all the work done in the `install()` method.
```js
export default class MyPlugin extends UIPlugin {
// ...
uninstall() {
this.uppy.off('upload-progress', this.onProgress);
this.uppy.removePostProcessor(this.afterUpload);
}
}
```
#### `afterUpdate()`
Called after every state update with a debounce, after everything has mounted.
#### `addTarget()`
Use this to add your plugin to another plugins target. This is what
`@uppy/dashboard` uses to add other plugins to its UI.
### `UIPlugin`
`UIPlugin` extends the `BasePlugin` class so it will also contain all the above
methods.
#### `mount(target)`
Mount this plugin to the `target` element. `target` can be a CSS query selector,
a DOM element, or another Plugin. If `target` is a Plugin, the source (current)
plugin will register with the target plugin, and the latter can decide how and
where to render the source plugin.
This method can be overridden to support for different render engines.
#### `render()`
Render this plugins UI. Uppy uses [Preact](https://preactjs.com) as its view
engine, so `render()` should return a Preact element. `render` is automatically
called by Uppy on each state change.
#### `onMount()`
Called after Preact has rendered the components of the plugin.
#### `update(state)`
Called on each state update. You will rarely need to use this, unless if you
want to build a UI plugin using something other than Preact.
#### `onUnmount()`
Called after the elements have been removed from the DOM. Can be used to do some
clean up or other side-effects.
## Upload Hooks
When creating an upload, Uppy runs files through an upload pipeline. The
pipeline consists of three parts, each of which can be hooked into:
Preprocessing, Uploading, and Postprocessing. Preprocessors can be used to
configure uploader plugins, encrypt files, resize images, etc., before uploading
them. Uploaders do the actual uploading work, such as creating an XMLHttpRequest
object and sending the file. Postprocessors do their work after files have been
uploaded completely. This could be anything from waiting for a file to propagate
across a CDN, to sending another request to relate some metadata to the file.
Each hook is a function that receives an array containing the file IDs that are
being uploaded, and returns a Promise to signal completion. Hooks are added and
removed through `Uppy` methods:
[`addPreProcessor`](/docs/uppy#addpreprocessorfn),
[`addUploader`](/docs/uppy#adduploaderfn),
[`addPostProcessor`](/docs/uppy#addpostprocessorfn), and their
[`remove*`](/docs/uppy#removepreprocessorremoveuploaderremovepostprocessorfn)
counterparts. Normally, hooks should be added during the plugin `install()`
method, and removed during the `uninstall()` method.
Additionally, upload hooks can fire events to signal progress.
When adding hooks, make sure to bind the hook `fn` beforehand! Otherwise, it
will be impossible to remove. For example:
```js
class MyPlugin extends BasePlugin {
constructor(uppy, opts) {
super(uppy, opts);
this.id = opts.id || 'MyPlugin';
this.type = 'example';
this.prepareUpload = this.prepareUpload.bind(this); // ← this!
}
prepareUpload(fileIDs) {
console.log(this); // `this` refers to the `MyPlugin` instance.
return Promise.resolve();
}
install() {
this.uppy.addPreProcessor(this.prepareUpload);
}
uninstall() {
this.uppy.removePreProcessor(this.prepareUpload);
}
}
```
Or you can define the method as a class field:
```js
class MyPlugin extends UIPlugin {
constructor(uppy, opts) {
super(uppy, opts);
this.id = opts.id || 'MyPlugin';
this.type = 'example';
}
prepareUpload = (fileIDs) => {
// ← this!
console.log(this); // `this` refers to the `MyPlugin` instance.
return Promise.resolve();
};
install() {
this.uppy.addPreProcessor(this.prepareUpload);
}
uninstall() {
this.uppy.removePreProcessor(this.prepareUpload);
}
}
```
## Progress events
Progress events can be fired for individual files to show feedback to the user.
For upload progress events, only emitting how many bytes are expected and how
many have been uploaded is enough. Uppy will handle calculating progress
percentages, upload speed, etc.
Preprocessing and postprocessing progress events are plugin-dependent and can
refer to anything, so Uppy doesnt try to be smart about them. Processing
progress events can be of two types: determinate or indeterminate. Some
processing does not have meaningful progress beyond “not done” and “done”. For
example, sending a request to initialize a server-side resource that will serve
as the upload destination. In those situations, indeterminate progress is
suitable. Other processing does have meaningful progress. For example,
encrypting a large file. In those situations, determinate progress is suitable.
Here are the relevant events:
* [`preprocess-progress`](/docs/uppy#preprocess-progress)
* [`upload-progress`](/docs/uppy#upload-progress)
* [`postprocess-progress`](/docs/uppy#postprocess-progress)
## JSX
Since Uppy uses Preact and not React, the default Babel configuration for JSX
elements does not work. You have to import the Preact `h` function and tell
Babel to use it by adding a `/** @jsx h */` comment at the top of the file.
See the Preact
[Getting Started Guide](https://preactjs.com/guide/getting-started) for more on
Babel and JSX.
<!-- eslint-disable jsdoc/check-tag-names -->
```jsx
/** @jsx h */
import { UIPlugin } from '@uppy/core';
import { h } from 'preact';
class NumFiles extends UIPlugin {
render() {
const numFiles = Object.keys(this.uppy.state.files).length;
return <div>Number of files: {numFiles}</div>;
}
}
```
## Locales
For any user facing language that you use while writing your Plugin, please
provide them as strings in the `defaultLocale` property like so:
```js
this.defaultLocale = {
strings: {
youCanOnlyUploadFileTypes: 'You can only upload: %{types}',
youCanOnlyUploadX: {
0: 'You can only upload %{smart_count} file',
1: 'You can only upload %{smart_count} files',
2: 'You can only upload %{smart_count} files',
},
},
};
```
This allows them to be overridden by Locale Packs, or directly when users pass
`locale: { strings: youCanOnlyUploadFileTypes: 'Something else completely about %{types}'} }`.
For this to work, its also required that you call `this.i18nInit()` in the
plugin constructor.
## Example of a custom plugin
Below is a full example of a
[small plugin](https://github.com/arturi/uppy-plugin-image-compressor) that
compresses images before uploading them. You can replace `compressorjs` method
with any other work you need to do. This works especially well for async stuff,
like calling an external API.
<!-- eslint-disable consistent-return -->
```js
import { UIPlugin } from '@uppy/core';
import Translator from '@uppy/utils/lib/Translator';
import Compressor from 'compressorjs/dist/compressor.esm.js';
class UppyImageCompressor extends UIPlugin {
constructor(uppy, opts) {
const defaultOptions = {
quality: 0.6,
};
super(uppy, { ...defaultOptions, ...opts });
this.id = this.opts.id || 'ImageCompressor';
this.type = 'modifier';
this.defaultLocale = {
strings: {
compressingImages: 'Compressing images...',
},
};
// we use those internally in `this.compress`, so they
// should not be overridden
delete this.opts.success;
delete this.opts.error;
this.i18nInit();
}
compress(blob) {
return new Promise(
(resolve, reject) =>
new Compressor(blob, {
...this.opts,
success(result) {
return resolve(result);
},
error(err) {
return reject(err);
},
}),
);
}
prepareUpload = (fileIDs) => {
const promises = fileIDs.map((fileID) => {
const file = this.uppy.getFile(fileID);
this.uppy.emit('preprocess-progress', file, {
mode: 'indeterminate',
message: this.i18n('compressingImages'),
});
if (!file.type.startsWith('image/')) {
return;
}
return this.compress(file.data)
.then((compressedBlob) => {
this.uppy.log(
`[Image Compressor] Image ${file.id} size before/after compression: ${file.data.size} / ${compressedBlob.size}`,
);
this.uppy.setFileState(fileID, { data: compressedBlob });
})
.catch((err) => {
this.uppy.log(
`[Image Compressor] Failed to compress ${file.id}:`,
'warning',
);
this.uppy.log(err, 'warning');
});
});
const emitPreprocessCompleteForAll = () => {
fileIDs.forEach((fileID) => {
const file = this.uppy.getFile(fileID);
this.uppy.emit('preprocess-complete', file);
});
};
// Why emit `preprocess-complete` for all files at once, instead of
// above when each is processed?
// Because it leads to StatusBar showing a weird “upload 6 files” button,
// while waiting for all the files to complete pre-processing.
return Promise.all(promises).then(emitPreprocessCompleteForAll);
};
install() {
this.uppy.addPreProcessor(this.prepareUpload);
}
uninstall() {
this.uppy.removePreProcessor(this.prepareUpload);
}
}
export default UppyImageCompressor;
```

View file

@ -0,0 +1,11 @@
---
sidebar_position: 4
---
# Building your own UI with Uppy
:::note
This guide is in progress.
:::

View file

@ -0,0 +1,93 @@
---
sidebar_position: 1
---
# Choosing the uploader you need
Versatile, reliable uploading is at the heart of Uppy. It has many configurable
plugins to suit your needs. In this guide we will explain the different plugins,
their strategies, and when to use them based on use cases.
## Use cases
### I want worry-free, plug-and-play uploads with Transloadit services
Transloadits strength is versatility. By doing video, audio, images, documents,
and more, you only need one vendor for [all your file processing
needs][transloadit-services]. The [`@uppy/transloadit`][] plugin directly
uploads to Transloadit so you only have to worry about creating a
[template][transloadit-concepts]. It uses
[Tus](#i-want-reliable-resumable-uploads) under the hood so you dont have to
sacrifice reliable, resumable uploads for convenience.
You should use [`@uppy/transloadit`][] if you dont want to host your own
server, (optionally) need file processing, and store it in the service (such as
S3 or GCS) of your liking. All with minimal effort.
### I want reliable, resumable uploads
[Tus][tus] is a new open protocol for resumable uploads built on HTTP. This
means accidentally closing your tab or losing connection lets you continue, for
instance, your 10GB upload instead of starting all over.
Tus supports any language, any platform, and any network. It requires a client
and server integration to work. You can checkout the client and server
[implementations][tus-implementations] to find the server in your preferred
language. You can store files on the Tus server itself, but you can also use
service integrations (such as S3) to store files externally.
If you want reliable, resumable uploads: use [`@uppy/tus`][] to connect to your
Tus server in a few lines of code.
:::tip
If you plan to let people upload _a lot_ of files, [`@uppy/tus`][] has
exponential backoff built-in. Meaning if your server (or proxy) returns HTTP 429
because its being overloaded, [`@uppy/tus`][] will find the ideal sweet spot to
keep uploading without overloading.
:::
### I want to upload to AWS S3 (or S3-compatible storage) directly
When you prefer a _client-to-storage_ over a _client-to-server-to-storage_ (such
as [Transloadit](/docs/transloadit) or [Tus](/docs/tus)) setup. This may in some
cases be preferable, for instance, to reduce costs or the complexity of running
a server and load balancer with [Tus](/docs/tus).
Uppy has two plugins to make this happen [`@uppy/aws-s3`][] and
[`@uppy/aws-s3-multipart`][], but we are planning to merge the two plugins in
the next major. You should use [`@uppy/aws-s3`][] with the new
`shouldUseMultipart` option.
:::info
You can also save files in S3 with the [`/s3/store`][s3-robot] robot while still
using the powers of Transloadit services.
:::
### I want to send regular HTTP uploads to my own server
[`@uppy/xhr-upload`][] handles classic HTML multipart form uploads as well as
uploads using the HTTP `PUT` method.
[s3-robot]: https://transloadit.com/services/file-exporting/s3-store/
[transloadit-services]: https://transloadit.com/services/
[transloadit-concepts]: https://transloadit.com/docs/getting-started/concepts/
[`@uppy/transloadit`]: /docs/transloadit
[`@uppy/tus`]: /docs/tus
[`@uppy/aws-s3-multipart`]: /docs/aws-s3-multipart
[`@uppy/aws-s3`]: /docs/aws-s3-multipart
[`@uppy/xhr-upload`]: /docs/xhr-upload
[tus]: https://tus.io/
[tus-implementations]: https://tus.io/implementations.html

View file

@ -0,0 +1,136 @@
# Custom stores
If your app uses a state management library such as
[Redux](https://redux.js.org), it can be useful to have Uppy store its state
there instead—that way, you could write custom uploader UI components in the
same way as the other components in the application.
Uppy comes with two state management solutions (stores):
* `@uppy/store-default`, a basic object-based store.
* `@uppy/store-redux`, a store that uses a key in a Redux store.
You can also use a third-party store:
* [uppy-store-ngrx](https://github.com/rimlin/uppy-store-ngrx/), keeping Uppy
state in a key in an [Ngrx](https://github.com/ngrx/platform) store for use
with Angular.
## Using stores
To use a store, pass an instance to the
[`store` option](/docs/uppy#store-defaultstore) in the Uppy constructor:
```js
import DefaultStore from '@uppy/store-default';
const uppy = new Uppy({
store: new DefaultStore(),
});
```
### `DefaultStore`
Uppy uses the `DefaultStore` by default! You do not need to do anything to use
it. It does not take any options.
### `ReduxStore`
The `ReduxStore` stores Uppy state on a key in an existing Redux store. The
`ReduxStore` dispatches `uppy/STATE_UPDATE` actions to update state. When the
state in Redux changes, it notifies Uppy. This way, you get most of the benefits
of Redux, including support for the Redux Devtools and time traveling!
Checkout our
[Redux example](https://github.com/transloadit/uppy/tree/main/examples/redux)
for a working demo.
#### `opts.store`
Pass a Redux store instance, from `Redux.createStore`. This instance should have
the Uppy reducer mounted somewhere already.
#### `opts.id`
By default, the `ReduxStore` assumes Uppy state is stored on a `state.uppy[id]`
key. `id` is randomly generated by the store constructor, but can be specified
by passing an `id` option if it should be predictable.
```js
ReduxStore({
store,
id: 'avatarUpload',
});
```
#### `opts.selector`
If youd rather not store the Uppy state under the `state.uppy` key at all, use
the `selector` option to the `ReduxStore` constructor to tell it where to find
state instead:
```js
const uppy = new Uppy({
store: ReduxStore({
store,
id: 'avatarUpload',
selector: (state) => state.pages.profile.uppy.avatarUpload,
}),
});
```
Note that when specifying a custom selector, you **must** also specify a custom
store ID. The store `id` tells the reducer in which property it should put
Uppys state. The selector must then take the state from that property. In the
example, we set the ID to `avatarUpload` and take the state from the
`[reducer mount path].avatarUpload`.
If your app uses [`reselect`](https://npmjs.com/package/reselect), its selectors
work well with this!
## Implementing Stores
An Uppy store is an object with three methods.
* `getState()` - Return the current state object.
* `setState(patch)` - Merge the object `patch` into the current state.
* `subscribe(listener)` - Call `listener` whenever the state changes. `listener`
is a function that should receive three parameters:
`(prevState, nextState, patch)`
The `subscribe()` method should return a function that “unsubscribes”
(removes) the `listener`.
The default store implementation, for example, looks a bit like this:
```js
function createDefaultStore() {
let state = {};
const listeners = new Set();
return {
getState: () => state,
setState: (patch) => {
const prevState = state;
const nextState = { ...prevState, ...patch };
state = nextState;
listeners.forEach((listener) => {
listener(prevState, nextState, patch);
});
},
subscribe: (listener) => {
listeners.add(listener);
return () => listeners.remove(listener);
},
};
}
```
A pattern like this, where users can pass options via a function call if
necessary, is recommended.
See the
[@uppy/store-default](https://github.com/transloadit/uppy/tree/main/packages/%40uppy/store-default)
package for more inspiration.

View file

@ -0,0 +1,651 @@
# Migration guides
These cover all the major Uppy versions and how to migrate to them.
## Migrate from Robodog to Uppy plugins
Uppy is flexible and extensible through plugins. But the integration code could
sometimes be daunting. This is what brought Robodog to life. An alternative with
the same features, but with a more ergonomic and minimal API.
But, it didnt come with its own set of new problems:
* It tries to do the exact same, but it looks like a different product.
* Its confusing for users whether they want to use Robodog or Uppy directly.
* Robodog is more ergonomic because its limited. When you hit such a limit, you
need to refactor everything to Uppy with plugins.
This has now led us to deprecating Robodog and embrace Uppy for its strong
suits; modularity and flexibility. At the same time, we also introduced
something to take away some repetitive integration code:
[`@uppy/remote-sources`](/docs/remote-sources).
To mimic the Robodog implementation with all its features, you can use the code
snippet below. But chances are Robodog did more than you need so feel free to
remove things or go through the [list of plugins](/docs/companion/) and install
and use the ones you need.
You can also checkout how we migrated the Robodog example ourselves in this
[commit](https://github.com/transloadit/uppy/commit/089aaed615c77bafaf905e291b6b4e82aaeb2f6f).
```js
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import RemoteSources from '@uppy/remote-sources';
import Webcam from '@uppy/webcam';
import ScreenCapture from '@uppy/screen-capture';
import GoldenRetriever from '@uppy/golden-retriever';
import ImageEditor from '@uppy/image-editor';
import Audio from '@uppy/audio';
import Transloadit, {
COMPANION_URL,
COMPANION_ALLOWED_HOSTS,
} from '@uppy/transloadit';
import '@uppy/core/dist/style.css';
import '@uppy/dashboard/dist/style.css';
import '@uppy/audio/dist/style.css';
import '@uppy/screen-capture/dist/style.css';
import '@uppy/image-editor/dist/style.css';
new Uppy()
.use(Dashboard, {
inline: true,
target: '#app',
showProgressDetails: true,
proudlyDisplayPoweredByUppy: true,
})
.use(RemoteSources, {
companionUrl: COMPANION_URL,
companionAllowedHosts: COMPANION_ALLOWED_HOSTS,
})
.use(Webcam, {
target: Dashboard,
showVideoSourceDropdown: true,
showRecordingLength: true,
})
.use(Audio, {
target: Dashboard,
showRecordingLength: true,
})
.use(ScreenCapture, { target: Dashboard })
.use(ImageEditor, { target: Dashboard })
.use(Transloadit, {
service: 'https://api2.transloadit.com',
async getAssemblyOptions(file) {
// This is where you configure your auth key, auth secret, and template ID
// /uppy/docs/transloadit/#getAssemblyOptions-file
//
// It is important to set the secret in production:
// https://transloadit.com/docs/topics/signature-authentication/
const response = await fetch('/some-endpoint');
return response.json();
},
});
```
## Migrate from Uppy 2.x to 3.x
### Uppy is pure ESM
Following the footsteps of many packages, we now only ship Uppy core and its
plugins as
[ECMAScript Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)
(ESM). On Uppy 2.x, we were shipping CommonJS.
If are already using ESM yourself, or are using the CDN builds, nothing changes
for you!
If you are using CommonJS, you might need to add some tooling for everything to
work, or you might want to refactor your codebase to ESM refer to the
[Pure ESM package](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c)
gist for added information and help on how to do that.
### Robodog is deprecated
See the [Robodog migration guide](#Migrate-from-Robodog-to-Uppy-plugins).
### `@uppy/core`
#### Remove `AggregateError` polyfill.
Its supported by most modern browsers and
[can be polyfilled by the user](https://github.com/transloadit/uppy/pull/3532#discussion_r818602636)
if needed.
To migrate: install a `AggregateError` polyfill or use `core-js`.
#### Remove `reset()` method.
Its a duplicate of `cancelAll`, but with a less intention revealing name.
To migrate: use `cancelAll`.
#### Remove backwards compatible exports (static properties on `Uppy`)\`
`Uppy`, `UIPlugin`, `BasePlugin`, and `debugLogger` used to also be accessible
on the `Uppy` export. This has now been removed due to the transition to ESM.
To migrate: import the `Uppy` class by default and/or use named exports for
everything else.
#### `uppy.validateRestrictions()` now returns a `RestrictionError`
This method used to return `{ result: false, reason: err.message }`, but that
felt strange as it tries to mimic an error. Instead it now return a
`RestrictionError`, which is extended `Error` class.
To migrate: check the return value, if its defined you have an error, otherwise
all went well. Note that the error is `return`ed, its not `throw`n, so you
dont have to `catch` it.
### `@uppy/transloadit`
Remove export of `ALLOWED_COMPANION_PATTERN`, `COMPANION`, and
`COMPANION_PATTERN` in favor of `COMPANION_URL` and `COMPANION_ALLOWED_HOSTS`.
This is to have more intention revealing names, `COMPANION` sounds like the
Companion instance, `COMPANION_URL` makes it more clear that its a URL.
These are properties can now be imported and used for remote sources plugins
when using Transloadit:
```js
import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit';
// ...
uppy.use(Dropbox, {
companionUrl: COMPANION_URL,
companionAllowedHosts: COMPANION_ALLOWED_HOSTS,
});
```
### `@uppy/aws-s3-multipart`
#### Make `headers` inside the return value of [`prepareUploadParts`](/docs/aws-s3-multipart/#prepareUploadParts-file-partData) part-indexed too.
This is to allow custom headers to be set per part. See this
[issue](https://github.com/transloadit/uppy/issues/3881) for details.
To migrate: make headers part indexed like `presignedUrls`:
`{ "headers": { "1": { "Content-MD5": "foo" } }}`.
#### Remove `client` getter and setter.
Its internal usage only.
To migrate: use exposed options only.
### `@uppy/tus/`, `@uppy/aws-s3`, `@uppy/xhr-upload`
Rename `metaFields` option to `allowedMetaFields`. Counter intuitively,
`metaFields` is for _filtering_ which `metaFields` to send along with the
request, not for adding extra meta fields to a request. As a lot of people were
confused by this, and the name overlaps with the
[`metaFields` option from Dashboard](/docs/dashboard/#metaFields), we renamed
it.
To migrate: use `allowedMetaFields`.
### `@uppy/react`
#### Uppy dependencies have become peer dependencies
`@uppy/dashboard`, `@uppy/drag-drop`, `@uppy/file-input`, `@uppy/progress-bar`,
and `@uppy/status-bar` are now peer dependencies. This means you dont install
all these packages if you only need one.
To migrate: install only the packages you need. If you use the Dashboard
component, you need `@uppy/dashboard`, and so onwards.
#### Dont expose `validProps` on the exported components.
Its internal usage only.
To migrate: use exposed options only.
### `@uppy/svelte`
`@uppy/dashboard`, `@uppy/drag-drop`, `@uppy/progress-bar`, and
`@uppy/status-bar` are now peer dependencies. This means you dont install all
these packages if you only need one.
To migrate: install only the packages you need. If you use the Dashboard
component, you need `@uppy/dashboard`, and so onwards.
### `@uppy/vue`
`@uppy/dashboard`, `@uppy/drag-drop`, `@uppy/file-input`, `@uppy/progress-bar`,
and `@uppy/status-bar` are now peer dependencies. This means you dont install
all these packages if you only need one.
To migrate: install only the packages you need. If you use the Dashboard
component, you need `@uppy/dashboard`, and so onwards.
### `@uppy/store-redux`
Remove backwards compatible exports (static properties on `ReduxStore`).
Exports, such as `reducer`, used to also be accessible on the `ReduxStore`
export. This has now been removed due to the transition to ESM.
To migrate: use named imports.
### `@uppy/thumbnail-generator`
Remove `rotateImage`, `protect`, and `canvasToBlob` from the plugin prototype.
They are internal usage only.
To migrate: use exposed options only.
### Known issues
* [`ERESOLVE could not resolve` on npm install](https://github.com/transloadit/uppy/issues/4057).
* [@uppy/svelte reports a broken dependency with the Vite bundler](https://github.com/transloadit/uppy/issues/4069).
## Migrate from Companion 3.x to 4.x
### Minimum required Node.js version is v14.20.0
Aligning with the Node.js
[Long Term Support (LTS) schedule](https://nodejs.org/en/about/releases/) and to
use modern syntax features.
### `companion.app()` returns `{ app, emitter }` instead of `app`
Companion 3.x provides the emitter as `companionEmitter` on `app`. As of 4.x, an
object is returned with an `app` property (express middleware) and an `emitter`
property (event emitter). This provides more flexibility in the future and
follows best practices.
### Removed `searchProviders` wrapper object inside `providerOptions`
To use [`@uppy/unsplash`](/docs/unsplash), you had to configure Unsplash in
Companion inside `providerOptions.searchProviders`. This is redundant, Unsplash
is a provider as well so we removed the wrapper object.
### Moved the `s3` options out of `providerOptions`
To use AWS S3 for storage, you configured the `s3` object inside
`providerOptions`. But as S3 is not a provider but a destination. To avoid
confusion we moved the `s3` settings to the root settings object.
### Removed compatibility for legacy Custom Provider implementations
[Custom Provider](/docs/companion/#Adding-custom-providers) implementations must
use the Promise API. The callback API is no longer supported.
### Default to no ACL for AWS S3
Default to no
[ACL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html)
for S3 uploads. Before the default was `public-read` but AWS now discourages
ACLs. The environment variable `COMPANION_AWS_DISABLE_ACL` is also removed,
instead Companion only uses `COMPANION_AWS_ACL`.
### `protocol` sent from Uppy in any `get` request is now required (before it would default to Multipart).
If you use any official Uppy plugins, then no migration is needed. For custom
plugins that talk to Companion, make to send along the `protocol` header with a
value of `multipart`, `s3Multipart`, or `tus`.
### `emitSuccess` and `emitError` are now private methods on the `Uploader` class.
Its unlikely youre using this, but its technically a breaking change. In
general, dont depend on implicitly internal methods, use exposed APIs instead.
### Removed `chunkSize` backwards compatibility for AWS S3 Multipart
`chunkSize` option will now be used as `partSize` in AWS multipart. Before only
valid values would be respected. Invalid values would be ignored. Now any value
will be passed on to the AWS SDK, possibly throwing an error on invalid values.
### Removed backwards compatibility for `/metrics` endpoint
The `metrics` option is a boolean flag to tell Companion whether to provide an
endpoint `/metrics` with Prometheus metrics. Metrics will now always be served
under `options.server.path`. Before v4.x, it would always be served under the
root.
For example: if `{ options: { metrics: true, server: { path: '/companion' }}}`,
metrics will now be served under `/companion/metrics`. In v3.x, the metrics
would be served under `/metrics`.
## Migrate from Uppy 1.x to 2.x
### New bundle requires manual polyfilling
With 2.0, following in the footsteps of Microsoft, we are dropping support for
IE11. As a result, we are able to remove all built-in polyfills, and the new
bundle size is **25% smaller**! If you want your app to still support older
browsers (such as IE11), you may need to add the following polyfills to your
bundle:
* [abortcontroller-polyfill](https://github.com/mo/abortcontroller-polyfill)
* [core-js](https://github.com/zloirock/core-js)
* [md-gum-polyfill](https://github.com/mozdevs/mediaDevices-getUserMedia-polyfill)
* [resize-observer-polyfill](https://github.com/que-etc/resize-observer-polyfill)
* [whatwg-fetch](https://github.com/github/fetch)
If youre using a bundler, you need import these before Uppy:
```js
import 'core-js';
import 'whatwg-fetch';
import 'abortcontroller-polyfill/dist/polyfill-patch-fetch';
// Order matters here: AbortController needs fetch, which needs Promise (provided by core-js).
import 'md-gum-polyfill';
import ResizeObserver from 'resize-observer-polyfill';
window.ResizeObserver ??= ResizeObserver;
export { default } from '@uppy/core';
export * from '@uppy/core';
```
If youre using Uppy from a CDN, we now provide two bundles: one for up-to-date
browsers that do not include polyfills and use modern syntax, and one for legacy
browsers. When migrating, be mindful about the types of browsers you want to
support:
```html
<!-- Modern browsers (recommended) -->
<script src="https://releases.transloadit.com/uppy/v3.17.0/uppy.min.js"></script>
<!-- Legacy browsers (IE11+) -->
<script
nomodule
src="https://releases.transloadit.com/uppy/v3.17.0/uppy.legacy.min.js"
></script>
<script type="module">
import 'https://releases.transloadit.com/uppy/v3.17.0/uppy.min.js';
</script>
```
Please note that while you may be able to get 2.0 to work in IE11 this way, we
do not officially support it anymore.
### Use `BasePlugin` or `UIPlugin` instead of `Plugin`
[`@uppy/core`][core] used to provide a `Plugin` class for creating plugins. This
was used for any official plugin, but also for users who want to create their
own custom plugin. But, `Plugin` always came bundled with Preact, even if the
plugin itself didnt add any UI elements.
`Plugin` has been replaced with `BasePlugin` and `UIPlugin`. `BasePlugin` is the
minimum you need to create a plugin and `UIPlugin` adds Preact for rendering
user interfaces.
You can import them from [`@uppy/core`][core]:
```js
import { BasePlugin, UIPlugin } from '@uppy/core';
```
**Note:** some bundlers will include `UIPlugin` (and thus Preact) if you import
from `@uppy/core`. To make sure this does not happen, you can import `Uppy` and
`BasePlugin` directly:
```js
import Uppy from '@uppy/core/lib/Uppy.js';
import BasePlugin from '@uppy/core/lib/BasePlugin.js';
```
### Use the latest Preact for your Uppy plugins
Official plugins have already been upgraded. If you are using any custom
plugins, upgrade Preact to the latest version. At the time of writing this is
`10.5.13`.
### Set plugin titles from locales
Titles for plugins used to be set with the `title` property in the plugin
options, but all other strings are set in `locale`. This has now been aligned.
You should set your plugin title from the `locale` property.
Before
```js
import Webcam from '@uppy/webcam';
uppy.use(Webcam, {
title: 'Some title',
});
```
After
```js
import Webcam from '@uppy/webcam';
uppy.use(Webcam, {
locale: {
strings: {
title: 'Some title',
},
},
});
```
### Initialize Uppy with the `new` keyword
The default export `Uppy` is no longer callable as a function. This means you
construct the `Uppy` instance using the `new` keyword.
```js
import Uppy from '@uppy/core';
const uppy = new Uppy(); // correct.
const otherUppy = Uppy(); // incorrect, will throw.
```
### Rename `allowMultipleUploads` to `allowMultipleUploadBatches`
[`allowMultipleUploadBatches`](/docs/uppy/#allowmultipleuploadbatches) means
allowing several calls to [`.upload()`](/docs/uppy/#upload), in other words, a
user can add more files after already having uploaded some.
<!--retext-simplify ignore multiple-->
We have renamed this to be more intention revealing that this is about uploads,
and not whether a user can choose multiple files for one upload.
```js
const uppy = new Uppy({
allowMultipleUploadBatches: true,
});
```
### New default limits for [`@uppy/xhr-upload`][xhr] and [`@uppy/tus`][tus]
The default limit has been changed from `0` to `5`. Setting this to `0` means no
limit on concurrent uploads.
You can change the limit on the Tus and XHR plugin options.
```js
uppy.use(Tus, {
// ...
limit: 10,
});
```
```js
uppy.use(XHRUpload, {
// ...
limit: 10,
});
```
### TypeScript changes
Uppy used to have loose types by default and strict types as an opt-in. The
default export was a function that returned the `Uppy` class, and the types came
bundled with the default export (`Uppy.SomeType`).
```ts
import Uppy from '@uppy/core';
import Tus from '@uppy/tus';
const uppy = Uppy<Uppy.StrictTypes>();
uppy.use(Tus, {
invalidOption: null, // this will make the compilation fail!
});
```
Uppy is now strictly typed by default and loose types have been removed.
```ts
// ...
const uppy = new Uppy();
uppy.use(Tus, {
invalidOption: null, // this will make the compilation fail!
});
```
Uppy types are now individual exports and should be imported separately.
<!-- eslint-disable @typescript-eslint/no-unused-vars -->
```ts
import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core';
```
#### Event types
[`@uppy/core`][core] provides an [`.on`](/docs/uppy/#uppy-on-39-event-39-action)
method to listen to [events](/docs/uppy/#Events). The types for these events
were loose and allowed for invalid events to be passed, such as
`uppy.on('upload-errrOOOoooOOOOOrrrr')`.
<!-- eslint-disable @typescript-eslint/no-unused-vars -->
```ts
// Before:
type Meta = { myCustomMetadata: string };
// Invalid event
uppy.on<Meta>('upload-errrOOOoooOOOOOrrrr', () => {
// ...
});
// After:
// Normal event signature
uppy.on('complete', (result) => {
const successResults = result.successful;
});
// Custom signature
type Meta = { myCustomMetadata: string };
// Notice how the custom type has now become the second argument
uppy.on<'complete', Meta>('complete', (result) => {
// The passed type is now merged into the `meta` types.
const meta = result.successful[0].meta.myCustomMetadata;
});
```
Plugins that add their own events can merge with existing ones in `@uppy/core`
with `declare module '@uppy/core' { ... }`. This is a TypeScript pattern called
[module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation).
For instance, when using [`@uppy/dashboard`][dashboard]:
<!-- eslint-disable @typescript-eslint/no-unused-vars -->
```ts
uppy.on('dashboard:file-edit-start', (file) => {
const fileName = file.name;
});
```
### Changes to pre-signing URLs for [`@uppy/aws-s3-multipart`][aws-s3-multipart]
See the Uppy 2.0.0 announcement post about the batch
[pre-signing URLs change](/blog/2021/08/2.0/#Batch-pre-signing-URLs-for-AWS-S3-Multipart).
`prepareUploadPart` has been renamed to
[`prepareUploadParts`](/docs/aws-s3-multipart/#prepareUploadParts-file-partData)
(plural). See the documentation link on how to use this function.
### Removed the `.run` method from [`@uppy/core`][core]
The `.run` method on the `Uppy` instance has been removed. This method was
already obsolete and only logged a warning. As of this major version, it no
longer exists.
### Removed `resume` and `removeFingerprintOnSuccess` options from [`@uppy/tus`][tus]
Tus will now by default try to resume uploads if the upload has been started in
the past.
This also means tus will store some data in localStorage for each upload, which
will automatically be removed on success. Making `removeFingerprintOnSuccess`
obsolete too.
### Thats it!
Uppy 1.0 will continue to receive bug fixes for three more months (until <time datetime="2021-12-01">1 December 2021</time>), security fixes for one more
year (until <time datetime="2022-09-01">1 September 2022</time>), but no more
new features after today. Exceptions are unlikely, but _can_ be made to
accommodate those with commercial support contracts, for example.
We hope youll waste no time in taking Uppy 2.0 out for a walk. When you do,
please let us know what you thought of it on
[Reddit](https://www.reddit.com/r/javascript/comments/penbr7/uppy_file_uploader_20_smaller_and_faster_modular/),
[HN](https://news.ycombinator.com/item?id=28359287), ProductHunt, or
[Twitter](https://twitter.com/uppy_io/status/1432399270846603264). Were howling
at the moon to hear from you!
## Migrate from Companion 1.x to 2.x
### Prerequisite
Since v2, you now need to be running `node.js >= v10.20.1` to use Companion.
### ProviderOptions
In v2 the `google` and `microsoft` [providerOptions](/docs/companion/#Options)
have been changed to `drive` and `onedrive` respectively.
### OAuth Redirect URIs
On your Providers respective developer platforms, the OAuth redirect URIs that
you should supply has now changed from:
`http(s)://$COMPANION_HOST_NAME/connect/$AUTH_PROVIDER/callback` in v1
to:
`http(s)://$COMPANION_HOST_NAME/$PROVIDER_NAME/redirect` in v2
#### New Redirect URIs
<div class="table-responsive">
| Provider | New Redirect URI |
| ------------ | ------------------------------------------------- |
| Dropbox | `https://$COMPANION_HOST_NAME/dropbox/redirect` |
| Google Drive | `https://$COMPANION_HOST_NAME/drive/redirect` |
| OneDrive | `https://$COMPANION_HOST_NAME/onedrive/redirect` |
| Box | `https://$YOUR_COMPANION_HOST_NAME/box/redirect` |
| Facebook | `https://$COMPANION_HOST_NAME/facebook/redirect` |
| Instagram | `https://$COMPANION_HOST_NAME/instagram/redirect` |
</div>
<!-- definitions -->
[core]: /docs/uppy/
[xhr]: /docs/xhr-upload/
[dashboard]: /docs/dashboard/
[aws-s3-multipart]: /docs/aws-s3-multipart/
[tus]: /docs/tus/

1562
docs/locales.mdx Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
{
"label": "Presets",
"position": 9
}

View file

@ -0,0 +1,141 @@
---
sidebar_position: 1
slug: /remote-sources
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Remote sources
`@uppy/remote-sources` is a preset plugin (meaning it bundles and sets up other
plugins) to add all the available remote sources, such Instagram, Google Drive,
Dropbox, and others to Uppy Dashboard in one package.
:::note
Remote Sources requires Dashboard and automatically installs all its plugins to
it.
:::
## When should I use it?
`@uppy/remote-sources` aims to simplify the setup for adding Companion plugins,
when you want to share the configuration between plugins. If you want your users
to upload files from any of the remote sources that Uppy offers, this plugin is
recommended.
A [Companion](/docs/companion) instance is required for the Remote Sources
plugin to work. Companion handles authentication with the remote services (such
as Facebook, Dropbox, etc.), downloads the files, and uploads them to the
destination. This saves the user bandwidth, especially helpful if they are on a
mobile connection.
You can self-host Companion or get a hosted version with any
[Transloadit plan](https://transloadit.com/pricing/).
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/remote-sources
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/remote-sources
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { RemoteSources } from "{{UPPY_JS_URL}}"
const RemoteSources = new Uppy().use(RemoteSources)
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
```js {10} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import RemoteSources from '@uppy/remote-sources';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
new Uppy();
.use(Dashboard);
.use(RemoteSources, { companionUrl: 'https://your-companion-url' });
```
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `RemoteSources`).
#### `sources`
List of remote sources that will be enabled (`array`, default:
`['Box', 'Dropbox', 'Facebook', 'GoogleDrive','Instagram', 'OneDrive', 'Unsplash', 'Url', 'Zoom']`).
You dont need to specify them manually or change them, but if you want to alter
the order in which they appear in the Dashboard, or disable some sources, this
option is for you.
```js
uppy.use(RemoteSources, {
companionUrl: 'https://your-companion-url',
sources: ['Instagram', 'GoogleDrive', 'Unsplash', 'Url'],
});
```
#### `companionUrl`
URL to a [Companion](/docs/companion) instance (`string`, default: `null`).
#### `companionHeaders`
Custom headers that should be sent along to [Companion](/docs/companion) on
every request (`object`, default: `{}`).
#### `companionAllowedHosts`
The valid and authorized URL(s)/URL pattern(s) from which OAuth responses should
be accepted (`string | RegExp | Array<string | RegExp>`, Default:
`companionUrl`).
This value can be a `string`, a `RegExp` object, or an array of both.
This is useful when you have your [Companion](/docs/companion) running on
several hosts. Otherwise, the default value, which is `companionUrl`, should do
fine.
#### `companionCookiesRule`
This option correlates to the [`Request.credentials` value][], which tells the
plugin whether to send cookies to [Companion](/docs/companion) (`string`,
default: `same-origin`).
#### `target`
DOM element, CSS selector, or plugin to place the drag and drop area into
(`string`, `Element`, `Function`, or `UIPlugin`, default: `Dashboard`).
[`request.credentials` value]:
https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials

58
docs/quick-start.mdx Normal file
View file

@ -0,0 +1,58 @@
---
sidebar_position: 1
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
import { QuickStartLinks } from '../src/components/QuickStartLinks/QuickStartLinks.tsx';
# Quick start
Uppy is a sleek, modular JavaScript file uploader that integrates seamlessly
with any application. Its fast, has a comprehensible API and lets you worry
about more important problems than building a file uploader.
:::tip
You can take Uppy for a walk inside CodeSandbox with a
[minimal drag & drop](https://codesandbox.io/s/uppy-drag-drop-gyewzx?file=/src/index.js)
experience or a
[full featured dashboard](https://codesandbox.io/s/uppy-dashboard-xpxuhd).
:::
<QuickStartLinks
items={[
{
name: 'I want a full featured, extendable UI',
description: 'Learn more about the Dashboard',
link: '/docs/dashboard',
},
{
name: 'I want a minimal drag & drop UI',
description: 'We have a lightweight plugin for that',
link: '/docs/drag-drop',
},
{
name: 'Which uploader do I need?',
description: 'Choosing the uploader you need',
link: '/docs/guides/choosing-uploader',
},
{
name: 'I want to add files from remote sources',
description: 'Such as Google Drive, Dropbox, Instagram',
link: '/docs/companion',
},
{
name: 'Id like a project example',
description: 'Try out one of our extensive example projects',
link: 'https://github.com/transloadit/uppy/tree/main/examples',
},
{
name: 'I have a question',
description: 'Our community forum is there to help',
link: 'https://community.transloadit.com/',
},
]}
/>

View file

@ -0,0 +1,4 @@
{
"label": "Sources",
"position": 6
}

134
docs/sources/audio.mdx Normal file
View file

@ -0,0 +1,134 @@
---
sidebar_position: 3
slug: /audio
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Audio
The `@uppy/audio` plugin lets you record audio using a built-in or external
microphone, or any other audio device, on desktop and mobile. The UI shows real
time sound wavelength when recording.
:::tip
[Try out the live example](/examples) or take it for a spin in
[CodeSandbox](https://codesandbox.io/s/uppy-dashboard-xpxuhd).
:::
## When should I use this?
When you want users to record audio on their computer.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/audio
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/audio
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Dashboard, Audio } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(Dashboard, { inline: true, target: 'body' })
uppy.use(Audio, { target: Uppy.Dashboard })
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
```js {3,7,11} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import Audio from '@uppy/audio';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
import '@uppy/audio/dist/style.min.css';
new Uppy()
.use(Dashboard, { inline: true, target: 'body' })
.use(Audio, { target: Dashboard });
```
### API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'audio'`).
#### `title`
Configures the title / name shown in the UI, for instance, on Dashboard tabs
(`string`, default: `'Audio'`).
#### `target`
DOM element, CSS selector, or plugin to place the audio into (`string` or
`Element`, default: `null`).
#### `showAudioSourceDropdown`
Configures whether to show a dropdown to select audio device (`boolean`,
default: `false`).
#### `locale`
```js
export default {
strings: {
pluginNameAudio: 'Audio',
// Used as the label for the button that starts an audio recording.
// This is not visibly rendered but is picked up by screen readers.
startAudioRecording: 'Begin audio recording',
// Used as the label for the button that stops an audio recording.
// This is not visibly rendered but is picked up by screen readers.
stopAudioRecording: 'Stop audio recording',
// Title on the “allow access” screen
allowAudioAccessTitle: 'Please allow access to your microphone',
// Description on the “allow access” screen
allowAudioAccessDescription:
'In order to record audio, please allow microphone access for this site.',
// Title on the “device not available” screen
noAudioTitle: 'Microphone Not Available',
// Description on the “device not available” screen
noAudioDescription:
'In order to record audio, please connect a microphone or another audio input device',
// Message about file size will be shown in an Informer bubble
recordingStoppedMaxSize:
'Recording stopped because the file size is about to exceed the limit',
// Used as the label for the counter that shows recording length (`1:25`).
// This is not visibly rendered but is picked up by screen readers.
recordingLength: 'Recording length %{recording_length}',
// Used as the label for the submit checkmark button.
// This is not visibly rendered but is picked up by screen readers.
submitRecordedFile: 'Submit recorded file',
// Used as the label for the discard cross button.
// This is not visibly rendered but is picked up by screen readers.
discardRecordedFile: 'Discard recorded file',
},
};
```

View file

@ -0,0 +1,5 @@
{
"label": "Companion plugins",
"position": 3,
"collapsed": false
}

View file

@ -0,0 +1,189 @@
---
slug: /box
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Box
The `@uppy/box` plugin lets users import files from their
[Box](https://www.box.com/en-nl/home) account.
:::tip
[Try out the live example](/examples) or take it for a spin in
[CodeSandbox](https://codesandbox.io/s/uppy-dashboard-xpxuhd).
:::
## When should I use this?
When you want to let users import files from their
[Box](https://www.box.com/en-nl/home) account.
A [Companion](/docs/companion) instance is required for the Box plugin to work.
Companion handles authentication with Box, downloads the files, and uploads them
to the destination. This saves the user bandwidth, especially helpful if they
are on a mobile connection.
You can self-host Companion or get a hosted version with any
[Transloadit plan](https://transloadit.com/pricing/).
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/box
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/box
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Box } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(Box, {
// Options
})
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
Using Box requires setup in both Uppy and Companion.
### Use in Uppy
```js {10-13} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import Box from '@uppy/box';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
new Uppy().use(Dashboard, { inline: true, target: '#dashboard' }).use(Box, {
target: Dashboard,
companionUrl: 'https://your-companion.com',
});
```
### Use in Companion
You can create a Box App on the
[Box Developers site](https://app.box.com/developers/console).
Things to note:
- Choose `Custom App` and select the `Standard OAuth 2.0 (User Authentication)`
app type.
- You must enable full write access, or you will get
[403 when downloading files](https://support.box.com/hc/en-us/community/posts/360049195613-403-error-while-file-download-API-Call)
Youll be redirected to the app page. This page lists the client ID (app key)
and client secret (app secret), which you should use to configure Companion.
The app page has a `"Redirect URIs"` field. Here, add:
```
https://$YOUR_COMPANION_HOST_NAME/box/redirect
```
If you are using Transloadit hosted Companion:
```
https://api2.transloadit.com/companion/box/redirect
```
You can only use the integration with your own account initially. Make sure to
apply for production status on the app page before you publish your app, or your
users will not be able to sign in!
Configure the Box key and secret. With the standalone Companion server, specify
environment variables:
```shell
export COMPANION_BOX_KEY="Box API key"
export COMPANION_BOX_SECRET="Box API secret"
```
When using the Companion Node.js API, configure these options:
```js
companion.app({
providerOptions: {
box: {
key: 'Box API key',
secret: 'Box API secret',
},
},
});
```
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'Box'`).
#### `title`
Title / name shown in the UI, such as Dashboard tabs (`string`, default:
`'Box'`).
#### `target`
DOM element, CSS selector, or plugin to place the drag and drop area into
(`string` or `Element`, default: `null`).
#### `companionUrl`
URL to a [Companion](/docs/companion) instance (`string`, default: `null`).
#### `companionHeaders`
Custom headers that should be sent along to [Companion](/docs/companion) on
every request (`Object`, default: `{}`).
#### `companionAllowedHosts`
The valid and authorised URL(s) from which OAuth responses should be accepted
(`string` or `RegExp` or `Array`, default: `companionUrl`).
This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is
useful when you have your [Companion](/docs/companion) running on several hosts.
Otherwise, the default value should do fine.
#### `companionCookiesRule`
This option correlates to the
[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials)
(`string`, default: `'same-origin'`).
This tells the plugin whether to send cookies to [Companion](/docs/companion).
#### `locale`
```js
export default {
strings: {
pluginNameBox: 'Box',
},
};
```

View file

@ -0,0 +1,188 @@
---
slug: /dropbox
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Dropbox
The `@uppy/dropbox` plugin lets users import files from their
[Dropbox](https://www.dropbox.com) account.
:::tip
[Try out the live example](/examples) or take it for a spin in
[CodeSandbox](https://codesandbox.io/s/uppy-dashboard-xpxuhd).
:::
## When should I use this?
When you want to let users import files from their
[Dropbox](https://www.dropbox.com) account.
A [Companion](/docs/companion) instance is required for the Dropbox plugin to
work. Companion handles authentication with Dropbox, downloads the files, and
uploads them to the destination. This saves the user bandwidth, especially
helpful if they are on a mobile connection.
You can self-host Companion or get a hosted version with any
[Transloadit plan](https://transloadit.com/pricing/).
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/dropbox
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/dropbox
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Dropbox } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(Dropbox, {
// Options
})
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
Using Dropbox requires setup in both Uppy and Companion.
### Use in Uppy
```js {10-13} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import Dropbox from '@uppy/dropbox';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
new Uppy().use(Dashboard, { inline: true, target: '#dashboard' }).use(Dropbox, {
target: Dashboard,
companionUrl: 'https://your-companion.com',
});
```
### Use in Companion
You can create a Dropbox App on the
[Dropbox Developers site](https://www.dropbox.com/developers/apps/create).
Things to note:
- Choose the “Dropbox API”, not the business variant.
- Typically youll want “Full Dropbox” access, unless you are absolutely certain
that you need the other one.
Youll be redirected to the app page. This page lists the app key and app
secret, which you should use to configure Companion as shown above.
The app page has a “Redirect URIs” field. Here, add:
```
https://$YOUR_COMPANION_HOST_NAME/dropbox/redirect
```
If you are using Transloadit hosted Companion:
```
https://api2.transloadit.com/companion/dropbox/redirect
```
You can only use the integration with your own account initially. Make sure to
apply for production status on the app page before you publish your app, or your
users will not be able to sign in!
Configure the Dropbox key and secret. With the standalone Companion server,
specify environment variables:
```shell
export COMPANION_DROPBOX_KEY="Dropbox API key"
export COMPANION_DROPBOX_SECRET="Dropbox API secret"
```
When using the Companion Node.js API, configure these options:
```js
companion.app({
providerOptions: {
dropbox: {
key: 'Dropbox API key',
secret: 'Dropbox API secret',
},
},
});
```
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'Dropbox'`).
#### `title`
Title / name shown in the UI, such as Dashboard tabs (`string`, default:
`'Dropbox'`).
#### `target`
DOM element, CSS selector, or plugin to place the drag and drop area into
(`string` or `Element`, default: `null`).
#### `companionUrl`
URL to a [Companion](/docs/companion) instance (`string`, default: `null`).
#### `companionHeaders`
Custom headers that should be sent along to [Companion](/docs/companion) on
every request (`Object`, default: `{}`).
#### `companionAllowedHosts`
The valid and authorised URL(s) from which OAuth responses should be accepted
(`string` or `RegExp` or `Array`, default: `companionUrl`).
This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is
useful when you have your [Companion](/docs/companion) running on several hosts.
Otherwise, the default value should do fine.
#### `companionCookiesRule`
This option correlates to the
[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials)
(`string`, default: `'same-origin'`).
This tells the plugin whether to send cookies to [Companion](/docs/companion).
#### `locale`
```js
export default {
strings: {
pluginNameDropbox: 'Dropbox',
},
};
```

View file

@ -0,0 +1,187 @@
---
slug: /facebook
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Facebook
The `@uppy/facebook` plugin lets users import files from their
[Facebook](https://www.facebook.com) account.
:::tip
[Try out the live example](/examples) or take it for a spin in
[CodeSandbox](https://codesandbox.io/s/uppy-dashboard-xpxuhd).
:::
## When should I use this?
When you want to let users import files from their
[Facebook](https://www.facebook.com) account.
A [Companion](/docs/companion) instance is required for the Facebook plugin to
work. Companion handles authentication with Facebook, downloads the files, and
uploads them to the destination. This saves the user bandwidth, especially
helpful if they are on a mobile connection.
You can self-host Companion or get a hosted version with any
[Transloadit plan](https://transloadit.com/pricing/).
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/facebook
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/facebook
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Facebook } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(Facebook, {
// Options
})
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
Using Facebook requires setup in both Uppy and Companion.
### Use in Uppy
```js {10-13} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import Facebook from '@uppy/facebook';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
new Uppy()
.use(Dashboard, { inline: true, target: '#dashboard' })
.use(Facebook, {
target: Dashboard,
companionUrl: 'https://your-companion.com',
});
```
### Use in Companion
You can create a Facebook App on the
[Facebook Developers site](https://developers.facebook.com/).
The app page has a “Redirect URIs” field. Here, add:
```
https://$YOUR_COMPANION_HOST_NAME/facebook/redirect
```
If you are using Transloadit hosted Companion:
```
https://api2.transloadit.com/companion/facebook/redirect
```
You can only use the integration with your own account initially. Make sure to
apply for production status on the app page before you publish your app, or your
users will not be able to sign in!
You need to set up OAuth in your Facebook app for Companion to be able to
connect to users Facebook accounts. You have to enable “Advanced Access” for
the `user_photos` permission. A precondition of that is “Business Verification”
which involves setting up a Meta Business Account and submitting documents to
prove business ownership.
Configure the Facebook key and secret. With the standalone Companion server,
specify environment variables:
```shell
export COMPANION_FACEBOOK_KEY="Facebook API key"
export COMPANION_FACEBOOK_SECRET="Facebook API secret"
```
When using the Companion Node.js API, configure these options:
```js
companion.app({
providerOptions: {
facebook: {
key: 'Facebook API key',
secret: 'Facebook API secret',
},
},
});
```
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'Facebook'`).
#### `title`
Title / name shown in the UI, such as Dashboard tabs (`string`, default:
`'Facebook'`).
#### `target`
DOM element, CSS selector, or plugin to place the drag and drop area into
(`string` or `Element`, default: `null`).
#### `companionUrl`
URL to a [Companion](/docs/companion) instance (`string`, default: `null`).
#### `companionHeaders`
Custom headers that should be sent along to [Companion](/docs/companion) on
every request (`Object`, default: `{}`).
#### `companionAllowedHosts`
The valid and authorised URL(s) from which OAuth responses should be accepted
(`string` or `RegExp` or `Array`, default: `companionUrl`).
This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is
useful when you have your [Companion](/docs/companion) running on several hosts.
Otherwise, the default value should do fine.
#### `companionCookiesRule`
This option correlates to the
[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials)
(`string`, default: `'same-origin'`).
This tells the plugin whether to send cookies to [Companion](/docs/companion).
#### `locale`
```js
export default {
strings: {
pluginNameFacebook: 'Facebook',
},
};
```

View file

@ -0,0 +1,191 @@
---
slug: /google-drive
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Google Drive
The `@uppy/google-drive` plugin lets users import files from their
[Google Drive](https://www.drive.google.com) account.
:::tip
[Try out the live example](/examples) or take it for a spin in
[CodeSandbox](https://codesandbox.io/s/uppy-dashboard-xpxuhd).
:::
## When should I use this?
When you want to let users import files from their
[Google Drive](https://www.drive.google.com) account.
A [Companion](/docs/companion) instance is required for the Google Drive plugin
to work. Companion handles authentication with Google Drive, downloads the
files, and uploads them to the destination. This saves the user bandwidth,
especially helpful if they are on a mobile connection.
You can self-host Companion or get a hosted version with any
[Transloadit plan](https://transloadit.com/pricing/).
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/google-drive
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/google-drive
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, GoogleDrive } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(GoogleDrive, {
// Options
})
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
Using Google Drive requires setup in both Uppy and Companion.
### Use in Uppy
```js {10-13} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import GoogleDrive from '@uppy/google-drive';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
new Uppy()
.use(Dashboard, { inline: true, target: '#dashboard' })
.use(GoogleDrive, {
target: Dashboard,
companionUrl: 'https://your-companion.com',
});
```
### Use in Companion
To sign up for API keys, go to the
[Google Developer Console](https://console.developers.google.com/).
Create a project for your app if you dont have one yet.
- On the projects dashboard,
[enable the Google Drive API](https://developers.google.com/drive/api/v3/enable-drive-api).
- [Set up OAuth authorization](https://developers.google.com/drive/api/v3/about-auth).
- Under scopes, add the `https://www.googleapis.com/auth/drive.readonly` Drive
API scope.
- Due to this being a sensitive scope, your app must complete Googles OAuth
app verification before being granted access. See
[OAuth App Verification Help Center](https://support.google.com/cloud/answer/13463073)
for more information.
The app page has a `"Redirect URIs"` field. Here, add:
```
https://$YOUR_COMPANION_HOST_NAME/drive/redirect
```
If you are using Transloadit hosted Companion:
```
https://api2.transloadit.com/companion/drive/redirect
```
Google will give you an OAuth client ID and client secret.
Configure the Google Drive key and secret in Companion. With the standalone
Companion server, specify environment variables:
```shell
export COMPANION_GOOGLE_KEY="Google Drive OAuth client ID"
export COMPANION_GOOGLE_SECRET="Google Drive OAuth client secret"
```
When using the Companion Node.js API, configure these options:
```js
companion.app({
providerOptions: {
drive: {
key: 'Google Drive OAuth client ID',
secret: 'Google Drive OAuth client secret',
},
},
});
```
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'GoogleDrive'`).
#### `title`
Title / name shown in the UI, such as Dashboard tabs (`string`, default:
`'GoogleDrive'`).
#### `target`
DOM element, CSS selector, or plugin to place the drag and drop area into
(`string` or `Element`, default: `null`).
#### `companionUrl`
URL to a [Companion](/docs/companion) instance (`string`, default: `null`).
#### `companionHeaders`
Custom headers that should be sent along to [Companion](/docs/companion) on
every request (`Object`, default: `{}`).
#### `companionAllowedHosts`
The valid and authorised URL(s) from which OAuth responses should be accepted
(`string` or `RegExp` or `Array`, default: `companionUrl`).
This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is
useful when you have your [Companion](/docs/companion) running on several hosts.
Otherwise, the default value should do fine.
#### `companionCookiesRule`
This option correlates to the
[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials)
(`string`, default: `'same-origin'`).
This tells the plugin whether to send cookies to [Companion](/docs/companion).
#### `locale`
```js
export default {
strings: {
pluginNameGoogleDrive: 'GoogleDrive',
},
};
```

View file

@ -0,0 +1,181 @@
---
slug: /instagram
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Instagram
The `@uppy/instagram` plugin lets users import files from their
[Instagram](https://instagram.com) account.
:::tip
[Try out the live example](/examples) or take it for a spin in
[CodeSandbox](https://codesandbox.io/s/uppy-dashboard-xpxuhd).
:::
## When should I use this?
When you want to let users import files from their
[Instagram](https://instagram.com) account.
A [Companion](/docs/companion) instance is required for the Instagram plugin to
work. Companion handles authentication with Instagram, downloads the files, and
uploads them to the destination. This saves the user bandwidth, especially
helpful if they are on a mobile connection.
You can self-host Companion or get a hosted version with any
[Transloadit plan](https://transloadit.com/pricing/).
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/instagram
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/instagram
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Instagram } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(Instagram, {
// Options
})
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
Using Instagram requires setup in both Uppy and Companion.
### Use in Uppy
```js {10-13} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import Instagram from '@uppy/instagram';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
new Uppy()
.use(Dashboard, { inline: true, target: '#dashboard' })
.use(Instagram, {
target: Dashboard,
companionUrl: 'https://your-companion.com',
});
```
### Use in Companion
To sign up for API keys, go to the
[Instagram Platform from Meta](https://developers.facebook.com/products/instagram/).
Create a project for your app if you dont have one yet.
The app page has a `"Redirect URIs"` field. Here, add:
```
https://$YOUR_COMPANION_HOST_NAME/instagram/redirect
```
If you are using Transloadit hosted Companion:
```
https://api2.transloadit.com/companion/instagram/redirect
```
Meta will give you an OAuth client ID and client secret.
Configure the Instagram key and secret in Companion. With the standalone
Companion server, specify environment variables:
```shell
export COMPANION_INSTAGRAM_KEY="Instagram OAuth client ID"
export COMPANION_INSTAGRAM_SECRET="Instagram OAuth client secret"
```
When using the Companion Node.js API, configure these options:
```js
companion.app({
providerOptions: {
drive: {
key: 'Instagram OAuth client ID',
secret: 'Instagram OAuth client secret',
},
},
});
```
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'Instagram'`).
#### `title`
Title / name shown in the UI, such as Dashboard tabs (`string`, default:
`'Instagram'`).
#### `target`
DOM element, CSS selector, or plugin to place the drag and drop area into
(`string` or `Element`, default: `null`).
#### `companionUrl`
URL to a [Companion](/docs/companion) instance (`string`, default: `null`).
#### `companionHeaders`
Custom headers that should be sent along to [Companion](/docs/companion) on
every request (`Object`, default: `{}`).
#### `companionAllowedHosts`
The valid and authorised URL(s) from which OAuth responses should be accepted
(`string` or `RegExp` or `Array`, default: `companionUrl`).
This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is
useful when you have your [Companion](/docs/companion) running on several hosts.
Otherwise, the default value should do fine.
#### `companionCookiesRule`
This option correlates to the
[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials)
(`string`, default: `'same-origin'`).
This tells the plugin whether to send cookies to [Companion](/docs/companion).
#### `locale`
```js
export default {
strings: {
pluginNameInstagram: 'Instagram',
},
};
```

View file

@ -0,0 +1,181 @@
---
slug: /onedrive
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# OneDrive
The `@uppy/onedrive` plugin lets users import files from their
[OneDrive](https://onedrive.com) account.
:::tip
[Try out the live example](/examples) or take it for a spin in
[CodeSandbox](https://codesandbox.io/s/uppy-dashboard-xpxuhd).
:::
## When should I use this?
When you want to let users import files from their
[OneDrive](https://onedrive.com) account.
A [Companion](/docs/companion) instance is required for the OneDrive plugin to
work. Companion handles authentication with OneDrive, downloads the files, and
uploads them to the destination. This saves the user bandwidth, especially
helpful if they are on a mobile connection.
You can self-host Companion or get a hosted version with any
[Transloadit plan](https://transloadit.com/pricing/).
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/onedrive
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/onedrive
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, OneDrive } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(OneDrive, {
// Options
})
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
Using OneDrive requires setup in both Uppy and Companion.
### Use in Uppy
```js {10-13} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import OneDrive from '@uppy/onedrive';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
new Uppy()
.use(Dashboard, { inline: true, target: '#dashboard' })
.use(OneDrive, {
target: Dashboard,
companionUrl: 'https://your-companion.com',
});
```
### Use in Companion
To sign up for API keys, go to the
[Azure Platform from Microsoft](https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade).
Create a project for your app if you dont have one yet.
The app page has a `"Redirect URIs"` field. Here, add:
```
https://$YOUR_COMPANION_HOST_NAME/onedrive/redirect
```
If you are using Transloadit hosted Companion:
```
https://api2.transloadit.com/companion/onedrive/redirect
```
Microsoft will give you an OAuth client ID and client secret.
Configure the OneDrive key and secret in Companion. With the standalone
Companion server, specify environment variables:
```shell
export COMPANION_ONEDRIVE_KEY="OneDrive Application ID"
export COMPANION_ONEDRIVE_SECRET="OneDrive OAuth client secret value"
```
When using the Companion Node.js API, configure these options:
```js
companion.app({
providerOptions: {
onedrive: {
key: 'OneDrive Application ID',
secret: 'OneDrive OAuth client secret value',
},
},
});
```
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'OneDrive'`).
#### `title`
Title / name shown in the UI, such as Dashboard tabs (`string`, default:
`'OneDrive'`).
#### `target`
DOM element, CSS selector, or plugin to place the drag and drop area into
(`string` or `Element`, default: `null`).
#### `companionUrl`
URL to a [Companion](/docs/companion) instance (`string`, default: `null`).
#### `companionHeaders`
Custom headers that should be sent along to [Companion](/docs/companion) on
every request (`Object`, default: `{}`).
#### `companionAllowedHosts`
The valid and authorised URL(s) from which OAuth responses should be accepted
(`string` or `RegExp` or `Array`, default: `companionUrl`).
This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is
useful when you have your [Companion](/docs/companion) running on several hosts.
Otherwise, the default value should do fine.
#### `companionCookiesRule`
This option correlates to the
[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials)
(`string`, default: `'same-origin'`).
This tells the plugin whether to send cookies to [Companion](/docs/companion).
#### `locale`
```js
export default {
strings: {
pluginNameOneDrive: 'OneDrive',
},
};
```

View file

@ -0,0 +1,166 @@
---
slug: /unsplash
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Unsplash
The `@uppy/unsplash` plugin lets users import files from their
[Unsplash](https://unsplash.com) account.
:::tip
[Try out the live example](/examples) or take it for a spin in
[CodeSandbox](https://codesandbox.io/s/uppy-dashboard-xpxuhd).
:::
## When should I use this?
When you want to let users import files from their
[Unsplash](https://unsplash.com) account.
A [Companion](/docs/companion) instance is required for the Unsplash plugin to
work. Companion handles authentication with Unsplash, downloads the files, and
uploads them to the destination. This saves the user bandwidth, especially
helpful if they are on a mobile connection.
You can self-host Companion or get a hosted version with any
[Transloadit plan](https://transloadit.com/pricing/).
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/unsplash
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/unsplash
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Unsplash } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(Unsplash, {
// Options
})
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
Using Unsplash requires setup in both Uppy and Companion.
### Use in Uppy
```js {10-13} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import Unsplash from '@uppy/unsplash';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
new Uppy()
.use(Dashboard, { inline: true, target: '#dashboard' })
.use(Unsplash, {
target: Dashboard,
companionUrl: 'https://your-companion.com',
});
```
### Use in Companion
You can create a Unsplash App on the
[Unsplash Developers site](https://unsplash.com/developers). Youll be
redirected to the app page, this page lists the app key and app secret.
Configure the Unsplash key and secret. With the standalone Companion server,
specify environment variables:
```shell
export COMPANION_UNSPLASH_KEY="Unsplash API key"
export COMPANION_UNSPLASH_SECRET="Unsplash API secret"
```
When using the Companion Node.js API, configure these options:
```js
companion.app({
providerOptions: {
unsplash: {
key: 'Unsplash API key',
secret: 'Unsplash API secret',
},
},
});
```
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'Unsplash'`).
#### `title`
Title / name shown in the UI, such as Dashboard tabs (`string`, default:
`'Unsplash'`).
#### `target`
DOM element, CSS selector, or plugin to place the drag and drop area into
(`string` or `Element`, default: `null`).
#### `companionUrl`
URL to a [Companion](/docs/companion) instance (`string`, default: `null`).
#### `companionHeaders`
Custom headers that should be sent along to [Companion](/docs/companion) on
every request (`Object`, default: `{}`).
#### `companionAllowedHosts`
The valid and authorised URL(s) from which OAuth responses should be accepted
(`string` or `RegExp` or `Array`, default: `companionUrl`).
This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is
useful when you have your [Companion](/docs/companion) running on several hosts.
Otherwise, the default value should do fine.
#### `companionCookiesRule`
This option correlates to the
[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials)
(`string`, default: `'same-origin'`).
This tells the plugin whether to send cookies to [Companion](/docs/companion).
#### `locale`
```js
export default {
strings: {
pluginNameUnsplash: 'Unsplash',
},
};
```

View file

@ -0,0 +1,149 @@
---
slug: /url
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Import from URL
The `@uppy/url` plugin allows users to import files from the internet. Paste any
URL and it will be added!
:::tip
[Try out the live example](/examples) or take it for a spin in
[CodeSandbox](https://codesandbox.io/s/uppy-dashboard-xpxuhd).
:::
## When should I use this?
When you want to let users import files any URL.
A [Companion](/docs/companion) instance is required for the URL plugin to work.
This saves the user bandwidth, especially helpful if they are on a mobile
connection.
You can self-host Companion or get a hosted version with any
[Transloadit plan](https://transloadit.com/pricing/).
:::note
Companion has
[Server Side Request Forgery](https://owasp.org/www-community/attacks/Server_Side_Request_Forgery)
(SSRF) protections built-in so you dont have to worry about the security
implications of arbitrary URLs.
:::
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/url
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/url
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Url } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(Url, {
// Options
})
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
Using `@uppy/url` only requires setup in Uppy.
### Use in Uppy
```js {10-13} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import Url from '@uppy/url';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
new Uppy().use(Dashboard, { inline: true, target: '#dashboard' }).use(Url, {
target: Dashboard,
companionUrl: 'https://your-companion.com',
});
```
### Use in Companion
Companion supports this plugin out-of-the-box so integration is required on this
side.
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'Url'`).
#### `title`
Title / name shown in the UI, such as Dashboard tabs (`string`, default:
`'Url'`).
#### `target`
DOM element, CSS selector, or plugin to place the drag and drop area into
(`string` or `Element`, default: `null`).
#### `companionUrl`
URL to a [Companion](/docs/companion) instance (`string`, default: `null`).
#### `companionHeaders`
Custom headers that should be sent along to [Companion](/docs/companion) on
every request (`Object`, default: `{}`).
#### `companionAllowedHosts`
The valid and authorised URL(s) from which OAuth responses should be accepted
(`string` or `RegExp` or `Array`, default: `companionUrl`).
This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is
useful when you have your [Companion](/docs/companion) running on several hosts.
Otherwise, the default value should do fine.
#### `companionCookiesRule`
This option correlates to the
[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials)
(`string`, default: `'same-origin'`).
This tells the plugin whether to send cookies to [Companion](/docs/companion).
#### `locale`
```js
export default {
strings: {
pluginNameUrl: 'Url',
},
};
```

View file

@ -0,0 +1,160 @@
---
slug: /zoom
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Zoom
The `@uppy/zoom` plugin lets users import files from their
[Zoom](https://zoom.com) account.
:::tip
[Try out the live example](/examples) or take it for a spin in
[CodeSandbox](https://codesandbox.io/s/uppy-dashboard-xpxuhd).
:::
## When should I use this?
When you want to let users import files from their [Zoom](https://zoom.com)
account.
A [Companion](/docs/companion) instance is required for the Zoom plugin to work.
Companion handles authentication with Zoom, downloads the files, and uploads
them to the destination. This saves the user bandwidth, especially helpful if
they are on a mobile connection.
You can self-host Companion or get a hosted version with any
[Transloadit plan](https://transloadit.com/pricing/).
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/zoom
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/zoom
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Zoom } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(Zoom, {
// Options
})
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
Using Zoom requires setup in both Uppy and Companion.
### Use in Uppy
```js {10-13} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import Zoom from '@uppy/zoom';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
new Uppy().use(Dashboard, { inline: true, target: '#dashboard' }).use(Zoom, {
target: Dashboard,
companionUrl: 'https://your-companion.com',
});
```
### Use in Companion
Configure the Zoom key and secret. With the standalone Companion server, specify
environment variables:
```shell
export COMPANION_ZOOM_KEY="Zoom API key"
export COMPANION_ZOOM_SECRET="Zoom API secret"
```
When using the Companion Node.js API, configure these options:
```js
companion.app({
providerOptions: {
zoom: {
key: 'Zoom API key',
secret: 'Zoom API secret',
},
},
});
```
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'Zoom'`).
#### `title`
Title / name shown in the UI, such as Dashboard tabs (`string`, default:
`'Zoom'`).
#### `target`
DOM element, CSS selector, or plugin to place the drag and drop area into
(`string` or `Element`, default: `null`).
#### `companionUrl`
URL to a [Companion](/docs/companion) instance (`string`, default: `null`).
#### `companionHeaders`
Custom headers that should be sent along to [Companion](/docs/companion) on
every request (`Object`, default: `{}`).
#### `companionAllowedHosts`
The valid and authorised URL(s) from which OAuth responses should be accepted
(`string` or `RegExp` or `Array`, default: `companionUrl`).
This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is
useful when you have your [Companion](/docs/companion) running on several hosts.
Otherwise, the default value should do fine.
#### `companionCookiesRule`
This option correlates to the
[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials)
(`string`, default: `'same-origin'`).
This tells the plugin whether to send cookies to [Companion](/docs/companion).
#### `locale`
```js
export default {
strings: {
pluginNameZoom: 'Zoom',
},
};
```

166
docs/sources/file-input.mdx Normal file
View file

@ -0,0 +1,166 @@
---
sidebar_position: 3
slug: /file-input
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# File input
The `@uppy/file-input` plugin is the most barebones UI for selecting files — it
shows a single button that, when clicked, opens up the browsers file selector.
## When should I use it?
When you want users to select files from their local machine with a minimal UI.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/file-input
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/file-input
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, FileInput } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(FileInput, { target: document.body })
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
```js showLineNumbers
import Uppy from '@uppy/core';
import FileInput from '@uppy/file-input';
import '@uppy/core/dist/style.min.css';
import '@uppy/file-input/dist/style.css';
new Uppy().use(FileInput, { target: '#uppy-file-input' });
```
:::note
The `@uppy/file-input` plugin includes some basic styles for use with the
[`pretty`](#pretty-true) option, like shown in the
[example](/examples/xhrupload). You can also choose not to use it and provide
your own styles instead.
Import general Core styles from `@uppy/core/dist/style.css` first, then add the
File Input styles from `@uppy/file-input/dist/style.css`. A minified version is
also available as `style.min.css` at the same path. The way to do import depends
on your build system.
:::
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'FileInput'`).
#### `title`
Configures the title / name shown in the UI, for instance, on Dashboard tabs
(`string`, default: `'File Input'`).
#### `target`
DOM element, CSS selector, or plugin to place the audio into (`string` or
`Element`, default: `null`).
#### `pretty`
When true, display a styled button that, when clicked, opens the file selector
UI. When false, a plain old browser `<input type="file">` element is shown
(`boolean`, default: `true`).
#### `inputName`
The `name` attribute for the `<input type="file">` element (`string`, default:
`'files[]'`).
#### `locale`
```js
export default {
strings: {
// The same key is used for the same purpose by @uppy/robodog's `form()` API, but our
// locale pack scripts can't access it in Robodog. If it is updated here, it should
// also be updated there!
chooseFiles: 'Choose files',
},
};
```
## Custom file inpt
If you dont like the look/feel of the button rendered by `@uppy/file-input`,
feel free to forgo the plugin and use your own custom button on a page, like so:
```html
<input type="file" id="my-file-input" />
```
Then add this JS to attach it to Uppy:
```js
const uppy = new Uppy(/* ... */);
const fileInput = document.querySelector('#my-file-input');
fileInput.addEventListener('change', (event) => {
const files = Array.from(event.target.files);
files.forEach((file) => {
try {
uppy.addFile({
source: 'file input',
name: file.name,
type: file.type,
data: file,
});
} catch (err) {
if (err.isRestriction) {
// handle restrictions
console.log('Restriction error:', err);
} else {
// handle other errors
console.error(err);
}
}
});
});
// Clear the `<input>` after the upload or when the file was removed
// so the file can be uploaded again (see
// https://github.com/transloadit/uppy/issues/2640#issuecomment-731034781).
uppy.on('file-removed', () => {
fileInput.value = null;
});
uppy.on('complete', () => {
fileInput.value = null;
});
```

View file

@ -0,0 +1,151 @@
---
sidebar_position: 2
slug: /screen-capture
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Screen capture
The `@uppy/screen-capture` plugin can record your screen or an application and
save it as a video.
:::tip
[Try out the live example](/examples) or take it for a spin in
[CodeSandbox](https://codesandbox.io/s/uppy-dashboard-xpxuhd).
:::
## When should I use this?
When you want users record their screen on their computer. This plugin only
works on desktop browsers which support
[`getDisplayMedia API`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia).
If no support for the API is detected, Screen Capture wont be installed, so you
dont have to do anything.
:::note
To use the screen capture plugin in a Chromium-based browser,
[your site must be served over https](https://developers.google.com/web/updates/2015/10/chrome-47-webrtc#public_service_announcements).
This restriction does not apply on `localhost`, so you dont have to jump
through many hoops during development.
:::
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/screen-capture
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/screen-capture
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Dashboard, ScreenCapture } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(Dashboard, { inline: true, target: 'body' })
uppy.use(ScreenCapture, { target: Uppy.Dashboard })
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
```js {3,7,11} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import ScreenCapture from '@uppy/screen-capture';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
import '@uppy/screen-capture/dist/style.min.css';
new Uppy()
.use(Dashboard, { inline: true, target: 'body' })
.use(ScreenCapture, { target: Dashboard });
```
### API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'ScreenCapture'`).
#### `title`
Configures the title / name shown in the UI, for instance, on Dashboard tabs
(`string`, default: `'Screen Capture'`).
#### `target`
DOM element, CSS selector, or plugin to place the screen capture into (`string`
or `Element`, default: `null`).
#### `displayMediaConstraints`
Options passed to
[`MediaDevices.getDisplayMedia()`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia)
(`Object`, default: `null`).
See the
[`MediaTrackConstraints`](https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints)
for a list of options.
#### `userMediaConstraints`
Options passed to
[`MediaDevices.getUserMedia()`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia)
(`Object`, default: `null`).
See the
[`MediaTrackConstraints`](https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints)
for a list of options.
#### `preferredVideoMimeType`
Set the preferred mime type for video recordings, for example `'video/webm'`
(`string`, default: `null`).
If the browser supports the given mime type, the video will be recorded in this
format. If the browser does not support it, it will use the browser default.
If no preferred video mime type is given, the ScreenCapture plugin will prefer
types listed in the [`allowedFileTypes` restriction](/docs/uppy/#restrictions),
if any.
#### `locale`
```js
export default {
strings: {
startCapturing: 'Begin screen capturing',
stopCapturing: 'Stop screen capturing',
submitRecordedFile: 'Submit recorded file',
streamActive: 'Stream active',
streamPassive: 'Stream passive',
micDisabled: 'Microphone access denied by user',
recording: 'Recording',
},
};
```

253
docs/sources/webcam.mdx Normal file
View file

@ -0,0 +1,253 @@
---
sidebar_position: 1
slug: /webcam
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Webcam
The `@uppy/webcam` plugin lets you take photos and record videos with a built-in
camera on desktop and mobile devices.
:::tip
[Try out the live example](/examples) or take it for a spin in
[CodeSandbox](https://codesandbox.io/s/uppy-dashboard-xpxuhd).
:::
## When should I use it?
When you want your users to able to use their camera. This plugin is published
separately but made specifically for the [Dashboard](/docs/dashboard). You can
technically use it without it, but its not officially supported.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/webcam
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/webcam
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Dashboard, Webcam } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(Dashboard, { inline: true, target: 'body' })
uppy.use(Webcam, { target: Uppy.Dashboard })
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
:::note
To use the Webcam plugin in Chrome,
[your site must be served over https](https://developers.google.com/web/updates/2015/10/chrome-47-webrtc#public_service_announcements).
This restriction does not apply on `localhost`, so you dont have to jump
through many hoops during development.
:::
```js {3,7,11} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import Webcam from '@uppy/webcam';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
import '@uppy/webcam/dist/style.min.css';
new Uppy()
.use(Dashboard, { inline: true, target: 'body' })
.use(Webcam, { target: Dashboard });
```
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'Webcam'`).
#### `target`
DOM element, CSS selector, or plugin to place the webcam into (`string` or
`Element`, default: `null`).
#### `countdown`
When taking a picture: the amount of seconds to wait before actually taking a
snapshot (`boolean`, default: `false`).
If set to `false` or 0, the snapshot is taken right away. This also shows a
`Smile!` message through the [Informer](/docs/informer) before the picture is
taken.
#### `onBeforeSnapshot`
A hook function to call before a snapshot is taken (`Function`, default:
`Promise.resolve`).
The Webcam plugin will wait for the returned Promise to resolve before taking
the snapshot. This can be used to carry out variations on the `countdown` option
for example.
#### `modes`
The types of recording modes to allow (`Array`, default: `[]`).
- `video-audio` - Record a video file, capturing both audio and video.
- `video-only` - Record a video file with the webcam, but dont record audio.
- `audio-only` - Record an audio file with the users microphone.
- `picture` - Take a picture with the webcam.
By default, all modes are allowed, and the Webcam plugin will show controls for
recording video as well as taking pictures.
#### `mirror`
Configures whether to mirror preview image from the camera (`boolean`, default:
`true`).
This option is useful when taking a selfie with a front camera: when you wave
your right hand, you will see your hand on the right on the preview screen, like
in the mirror. But when you actually take a picture, it will not be mirrored.
This is how smartphone selfie cameras behave.
#### `videoConstraints`
Configure the [`MediaTrackConstraints`][] (`Object`, default: `{}`).
You can specify acceptable ranges for the resolution of the video stream using
the [`aspectRatio`][], [`width`][], and [`height`][] properties. Each property
takes an object with `{ min, ideal, max }` properties. For example, use
`width: { min: 720, max: 1920, ideal: 1920 }` to allow any width between 720 and
1920 pixels wide, while preferring the highest resolution.
Devices sometimes have several cameras, front and back, for example.
[`facingMode`][] lets you specify which should be used:
- `user`: The video source is facing toward the user; this includes, for
example, the front-facing camera on a smartphone.
- `environment`: The video source is facing away from the user, thereby viewing
their environment. This is the back camera on a smartphone.
- `left`: The video source is facing toward the user but to their left, such as
a camera aimed toward the user but over their left shoulder.
- `right`: The video source is facing toward the user but to their right, such
as a camera aimed toward the user but over their right shoulder.
For a full list of available properties, check out MDN documentation for
[`MediaTrackConstraints`][].
[`mediatrackconstraints`]:
https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints#Properties_of_video_tracks
[`aspectratio`]:
https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/aspectRatio
[`width`]:
https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/width
[`height`]:
https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/height
[`facingmode`]:
https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/facingMode
#### `showVideoSourceDropdown`
Configures whether to show a dropdown which enables to choose the video device
to use (`boolean`, default: `false`).
This option will have priority over `facingMode` if enabled.
#### `showRecordingLength`
Configures whether to show the length of the recording while the recording is in
progress (`boolean`, default: `false`).
#### `preferredVideoMimeType`
Set the preferred mime type for video recordings, for example `'video/webm'`
(`string`, default: `null`).
If the browser supports the given mime type, the video will be recorded in this
format. If the browser does not support it, it will use the browser default. If
no preferred video mime type is given, the Webcam plugin will prefer types
listed in the [`allowedFileTypes` restriction](/docs/uppy/#restrictions), if
any.
#### `preferredImageMimeType`
Set the preferred mime type for images, for example `'image/png'` (`string`,
default: `image/jpeg`).
If the browser supports rendering the given mime type, the image will be stored
in this format. Else `image/jpeg` is used by default. If no preferred image mime
type is given, the Webcam plugin will prefer types listed in the
[`allowedFileTypes` restriction](/docs/uppy/#restrictions), if any.
#### `mobileNativeCamera`
Replaces Uppys custom camera UI on mobile and tablet with the native device
camera (`Function: boolean` or `boolean`, default: `isMobile()`).
This will show the “Take Picture” and / or “Record Video” buttons, which ones
show depends on the [`modes`](#modes) option.
You can set a boolean to forcefully enable / disable this feature, or a function
which returns a boolean. By default we use the
[`is-mobile`](https://github.com/juliangruber/is-mobile) package.
#### `locale`
```js
export default {
strings: {
pluginNameCamera: 'Camera',
noCameraTitle: 'Camera Not Available',
noCameraDescription:
'In order to take pictures or record video, please connect a camera device',
recordingStoppedMaxSize:
'Recording stopped because the file size is about to exceed the limit',
submitRecordedFile: 'Submit recorded file',
discardRecordedFile: 'Discard recorded file',
// Shown before a picture is taken when the `countdown` option is set.
smile: 'Smile!',
// Used as the label for the button that takes a picture.
// This is not visibly rendered but is picked up by screen readers.
takePicture: 'Take a picture',
// Used as the label for the button that starts a video recording.
// This is not visibly rendered but is picked up by screen readers.
startRecording: 'Begin video recording',
// Used as the label for the button that stops a video recording.
// This is not visibly rendered but is picked up by screen readers.
stopRecording: 'Stop video recording',
// Used as the label for the recording length counter. See the showRecordingLength option.
// This is not visibly rendered but is picked up by screen readers.
recordingLength: 'Recording length %{recording_length}',
// Title on the “allow access” screen
allowAccessTitle: 'Please allow access to your camera',
// Description on the “allow access” screen
allowAccessDescription:
'In order to take pictures or record video with your camera, please allow camera access for this site.',
},
};
```

View file

@ -0,0 +1,4 @@
{
"label": "Uploaders",
"position": 7
}

View file

@ -0,0 +1,522 @@
---
sidebar_position: 4
slug: /aws-s3-multipart
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# AWS S3
The `@uppy/aws-s3` plugin can be used to upload files directly to a S3 bucket or
a S3-compatible provider, such as Google Cloud Storage or DigitalOcean Spaces.
Uploads can be signed using either [Companion][companion docs], temporary
credentials, or a custom signing function.
## When should I use it?
:::tip
Not sure which uploader is best for you? Read
“[Choosing the uploader you need](/docs/guides/choosing-uploader)”.
:::
You can use this plugin when you prefer a _client-to-storage_ over a
_client-to-server-to-storage_ (such as [Transloadit](/docs/transloadit) or
[Tus](/docs/tus)) setup. This may in some cases be preferable, for instance, to
reduce costs or the complexity of running a server and load balancer with
[Tus](/docs/tus).
Multipart uploads start to become valuable for larger files (100&nbsp;MiB+) as
it uploads a single object as a set of parts. This has certain benefits, such as
improved throughput (uploading parts in parallel) and quick recovery from
network issues (only the failed parts need to be retried). The downside is
request overhead, as it needs to do creation, signing (unless you are [signing
on the client][]), and completion requests besides the upload requests. For
example, if you are uploading files that are only a couple kilobytes with a
100ms roundtrip latency, you are spending 400ms on overhead and only a few
milliseconds on uploading.
**In short**
- We recommend to set [`shouldUseMultipart`][] to enable multipart uploads only
for large files.
- If you prefer to have less overhead (+20% upload speed) you can use temporary
S3 credentials with [`getTemporarySecurityCredentials`][]. This means users
get a single token which allows them to do bucket operations for longer,
instead of short lived signed URL per resource. This is a security trade-off.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/aws-s3
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/aws-s3
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, AwsS3 } from "{{UPPY_JS_URL}}"
new Uppy().use(AwsS3, { /* see options */ })
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
### Setting up your S3 bucket
To use this plugin with S3 we need to setup a bucket with the right permissions
and CORS settings.
S3 buckets do not allow public uploads for security reasons. To allow Uppy and
the browser to upload directly to a bucket, its CORS permissions need to be
configured.
CORS permissions can be found in the
[S3 Management Console](https://console.aws.amazon.com/s3/home). Click the
bucket that will receive the uploads, then go into the `Permissions` tab and
select the `CORS configuration` button. A JSON document will be shown that
defines the CORS configuration. (AWS used to use XML but now only allow JSON).
More information about the
[S3 CORS format here](https://docs.amazonaws.cn/en_us/AmazonS3/latest/userguide/ManageCorsUsing.html).
The configuration required for Uppy and Companion is this:
```json
[
{
"AllowedOrigins": ["https://my-app.com"],
"AllowedMethods": ["GET", "PUT"],
"MaxAgeSeconds": 3000,
"AllowedHeaders": [
"Authorization",
"x-amz-date",
"x-amz-content-sha256",
"content-type"
],
"ExposeHeaders": ["ETag", "Location"]
},
{
"AllowedOrigins": ["*"],
"AllowedMethods": ["GET"],
"MaxAgeSeconds": 3000
}
]
```
A good practice is to use two CORS rules: one for viewing the uploaded files,
and one for uploading files. This is done above where the first object in the
array defines the rules for uploading, and the second for viewing. The example
above **makes files publicly viewable**. You can change it according to your
needs.
If you are using an IAM policy to allow access to the S3 bucket, the policy must
have at least the `s3:PutObject` and `s3:PutObjectAcl` permissions scoped to the
bucket in question. In-depth documentation about CORS rules is available on the
[AWS documentation site](https://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html).
### Use with your own server
The recommended approach is to integrate `@uppy/aws-s3` with your own server.
You will need to do the following things:
1. [Setup a S3 bucket](#setting-up-your-s3-bucket).
2. [Setup your server](https://github.com/transloadit/uppy/blob/main/examples/aws-nodejs/index.js)
3. [Setup Uppy client](https://github.com/transloadit/uppy/blob/main/examples/aws-nodejs/public/index.html).
### Use with Companion
[Companion](/docs/companion) has S3 routes built-in for a plug-and-play
experience with Uppy.
:::caution
Generally its better for access control, observability, and scaling to
integrate `@uppy/aws-s3` with your own server. You may want to use
[Companion](/docs/companion) for creating, signing, and completing your S3
uploads if you already need Companion for remote files (such as from Google
Drive). Otherwise its not worth the hosting effort.
:::
```js {10} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import AwsS3 from '@uppy/aws-s3';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
const uppy = new Uppy()
.use(Dashboard, { inline: true, target: 'body' })
.use(AwsS3, {
shouldUseMultipart: (file) => file.size > 100 * 2 ** 20,
companionUrl: 'https://companion.uppy.io',
});
```
## API
### Options
#### `shouldUseMultipart(file)`
:::warning
Until the next major version, not setting this option uses the
[legacy version of this plugin](../aws-s3/). This is a suboptimal experience for
some of your users uploads. Its best for speed and stability to upload large
(100&nbsp;MiB+) files with multipart and small files with regular uploads.
:::
A boolean, or a function that returns a boolean which is called for each file
that is uploaded with the corresponding `UppyFile` instance as argument.
By default, all files are uploaded as multipart. In a future version, all files
with a `file.size` ≤ 100&nbsp;MiB will be uploaded in a single chunk, all files
larger than that as multipart.
Heres how to use it:
```js
uppy.use(AwsS3, {
shouldUseMultipart(file) {
// Use multipart only for files larger than 100MiB.
return file.size > 100 * 2 ** 20;
},
});
```
#### `limit`
The maximum amount of files to upload in parallel (`number`, default: `6`).
Note that the amount of files is not the same as the amount of concurrent
connections. Multipart uploads can use many requests per file. For example, for
a 100 MiB file with a part size of 5 MiB:
- 1 `createMultipartUpload` request
- 100/5 = 20 sign requests (unless you are [signing on the client][])
- 100/5 = 20 upload requests
- 1 `completeMultipartUpload` request
:::caution
Unless you have a good reason and are well informed about the average internet
speed of your users, do not set this higher. S3 uses HTTP/1.1, which means a
limit to concurrent connections and your uploads may expire before they are
uploaded.
:::
#### `companionUrl`
URL to a [Companion](/docs/companion) instance (`string`, default: `null`).
#### `companionHeaders`
Custom headers that should be sent along to [Companion](/docs/companion) on
every request (`Object`, default: `{}`).
#### `companionCookiesRule`
This option correlates to the
[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials)
(`string`, default: `'same-origin'`).
This tells the plugin whether to send cookies to [Companion](/docs/companion).
#### `retryDelays`
`retryDelays` are the intervals in milliseconds used to retry a failed chunk
(`array`, default: `[0, 1000, 3000, 5000]`).
This is also used for [`signPart()`](#signpartfile-partdata). Set to `null` to
disable automatic retries, and fail instantly if any chunk fails to upload.
#### `getChunkSize(file)`
A function that returns the minimum chunk size to use when uploading the given
file.
The S3 Multipart plugin uploads files in chunks. Chunks are sent in batches to
have presigned URLs generated with [`signPart()`](#signpartfile-partdata). To
reduce the amount of requests for large files, you can choose a larger chunk
size, at the cost of having to re-upload more data if one chunk fails to upload.
S3 requires a minimum chunk size of 5MiB, and supports at most 10,000 chunks per
multipart upload. If `getChunkSize()` returns a size thats too small, Uppy will
increase it to S3s minimum requirements.
#### `getUploadParameters(file, options)`
:::note
When using [Companion][companion docs] to sign S3 uploads, you should not define
this option.
:::
A function that will be called for each non-multipart upload.
- `file`: `UppyFile` the file that will be uploaded
- `options`: `object`
- `signal`: `AbortSignal`
- **Returns:** `object | Promise<object>`
- `method`: `string`, the HTTP method to be used for the upload. This should
be one of either `PUT` or `POST`, depending on the type of upload used.
- `url`: `string`, the URL to which the upload request will be sent. When
using a presigned PUT upload, this should be the URL to the S3 object with
signing parameters included in the query string. When using a POST upload
with a policy document, this should be the root URL of the bucket.
- `fields` `object`, an object with form fields to send along with the upload
request. For presigned PUT uploads (which are default), this should be left
empty.
- `headers`: `object`, an object with request headers to send along with the
upload request. When using a presigned PUT upload, its a good idea to
provide `headers['content-type']`. That will make sure that the request uses
the same content-type that was used to generate the signature. Without it,
the browser may decide on a different content-type instead, causing S3 to
reject the upload.
#### `createMultipartUpload(file)`
A function that calls the S3 Multipart API to create a new upload.
`file` is the file object from Uppys state. The most relevant keys are
`file.name` and `file.type`.
Return a Promise for an object with keys:
- `uploadId` - The UploadID returned by S3.
- `key` - The object key for the file. This needs to be returned to allow it to
be different from the `file.name`.
The default implementation calls out to Companions S3 signing endpoints.
#### `listParts(file, { uploadId, key })`
A function that calls the S3 Multipart API to list the parts of a file that have
already been uploaded.
Receives the `file` object from Uppys state, and an object with keys:
- `uploadId` - The UploadID of this Multipart upload.
- `key` - The object key of this Multipart upload.
Return a Promise for an array of S3 Part objects, as returned by the S3
Multipart API. Each object has keys:
- `PartNumber` - The index in the file of the uploaded part.
- `Size` - The size of the part in bytes.
- `ETag` - The ETag of the part, used to identify it when completing the
multipart upload and combining all parts into a single file.
The default implementation calls out to Companions S3 signing endpoints.
#### `signPart(file, partData)`
A function that generates a signed URL for the specified part number. The
`partData` argument is an object with the keys:
- `uploadId` - The UploadID of this Multipart upload.
- `key` - The object key in the S3 bucket.
- `partNumber` - cant be zero.
- `body` The data that will be signed.
- `signal` An `AbortSignal` that may be used to abort an ongoing request.
This function should return a object, or a promise that resolves to an object,
with the following keys:
- `url` the presigned URL, as a `string`.
- `headers` **(Optional)** Custom headers to send along with the request to S3
endpoint.
An example of what the return value should look like:
```json
{
"url": "https://bucket.region.amazonaws.com/path/to/file.jpg?partNumber=1&...",
"headers": { "Content-MD5": "foo" }
}
```
#### `abortMultipartUpload(file, { uploadId, key })`
A function that calls the S3 Multipart API to abort a Multipart upload, and
removes all parts that have been uploaded so far.
Receives the `file` object from Uppys state, and an object with keys:
- `uploadId` - The UploadID of this Multipart upload.
- `key` - The object key of this Multipart upload.
This is typically called when the user cancels an upload. Cancellation cannot
fail in Uppy, so the result of this function is ignored.
The default implementation calls out to Companions S3 signing endpoints.
#### `completeMultipartUpload(file, { uploadId, key, parts })`
A function that calls the S3 Multipart API to complete a Multipart upload,
combining all parts into a single object in the S3 bucket.
Receives the `file` object from Uppys state, and an object with keys:
- `uploadId` - The UploadID of this Multipart upload.
- `key` - The object key of this Multipart upload.
- `parts` - S3-style list of parts, an array of objects with `ETag` and
`PartNumber` properties. This can be passed straight to S3s Multipart API.
Return a Promise for an object with properties:
- `location` - **(Optional)** A publicly accessible URL to the object in the S3
bucket.
The default implementation calls out to Companions S3 signing endpoints.
#### `allowedMetaFields: null`
Pass an array of field names to limit the metadata fields that will be added to
upload as query parameters.
- Set this to `['name']` to only send the `name` field.
- Set this to `null` (the default) to send _all_ metadata fields.
- Set this to an empty array `[]` to not send any fields.
<details>
<summary>Deprecated options</summary>
#### `prepareUploadParts(file, partData)`
A function that generates a batch of signed URLs for the specified part numbers.
Receives the `file` object from Uppys state. The `partData` argument is an
object with keys:
- `uploadId` - The UploadID of this Multipart upload.
- `key` - The object key in the S3 bucket.
- `parts` - An array of objects with the part number and chunk
(`Array<{ number: number, chunk: blob }>`). `number` cant be zero.
`prepareUploadParts` should return a `Promise` with an `Object` with keys:
- `presignedUrls` - A JavaScript object with the part numbers as keys and the
presigned URL for each part as the value.
- `headers` - **(Optional)** Custom headers to send along with every request per
part (`{ 1: { 'Content-MD5': 'hash' }}`). These are (1-based) indexed by part
number too so you can for instance send the MD5 hash validation for each part
to S3.
An example of what the return value should look like:
```json
{
"presignedUrls": {
"1": "https://bucket.region.amazonaws.com/path/to/file.jpg?partNumber=1&...",
"2": "https://bucket.region.amazonaws.com/path/to/file.jpg?partNumber=2&...",
"3": "https://bucket.region.amazonaws.com/path/to/file.jpg?partNumber=3&..."
},
"headers": {
"1": { "Content-MD5": "foo" },
"2": { "Content-MD5": "bar" },
"3": { "Content-MD5": "baz" }
}
}
```
If an error occurred, reject the `Promise` with an `Object` with the following
keys:
```json
{ "source": { "status": 500 } }
```
`status` is the HTTP code and is required for determining whether to retry the
request. `prepareUploadParts` will be retried if the code is `0`, `409`, `423`,
or between `500` and `600`.
</details>
#### `getTemporarySecurityCredentials(options)`
:::note
When using [Companion][companion docs] as a backend, you can pass `true` instead
of a function. Setting up Companion will not simplify the process of getting
signing on the client.
:::
A boolean (when using Companion), or an (async) function to retrieve temporary
security credentials used for all uploads instead of signing every part. This
results in less request overhead which can lead to around 20% faster uploads.
This is a security tradeoff. We recommend to not use this option unless you are
familiar with the security implications of temporary credentials, and how to
setup your bucket to make it work. See the
[Requesting temporary security credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html)
AWS guide for more information.
Its strongly recommended to have some sort of caching process to avoid
requesting more temporary token than necessary.
- `options`: `object`
- `signal`: `AbortSignal`
- **Returns:** `object | Promise<object>`
- `credentials`: `object`
- `AccessKeyId`: `string`
- `SecretAccessKey`: `string`
- `SessionToken`: `string`
- `Expiration`: `string`
- `bucket`: `string`
- `region`: `string`
If you are using Companion (for example because you want to support remote
upload sources), you can pass a boolean:
```js
uppy.use(AwsS3, {
// This is an example using Companion:
companionUrl: 'http://companion.uppy.io',
getTemporarySecurityCredentials: true,
shouldUseMultipart: (file) => file.size > 100 * 2 ** 20,
});
```
In the most common case, you are using a different backend, in which case you
need to specify a function:
```js
uppy.use(AwsS3, {
// This is an example not using Companion:
async getTemporarySecurityCredentials({ signal }) {
const response = await fetch('/sts-token', { signal });
if (!response.ok)
throw new Error('Failed to fetch STS', { cause: response });
return response.json();
},
shouldUseMultipart: (file) => file.size > 100 * 2 ** 20,
});
```
[`gettemporarysecuritycredentials`]: #gettemporarysecuritycredentialsoptions
[`shouldusemultipart`]: #shouldusemultipartfile
[companion docs]: /docs/companion
[signing on the client]: #gettemporarysecuritycredentialsoptions

463
docs/uploader/aws-s3.mdx Normal file
View file

@ -0,0 +1,463 @@
---
sidebar_position: 3
slug: /aws-s3
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# AWS S3 (legacy)
The `@uppy/aws-s3` plugin can be used to upload files directly to a S3 bucket or
a S3-compatible provider, such as Google Cloud Storage or DigitalOcean Spaces.
Uploads can be signed using either [Companion][companion docs] or a custom
signing function.
This documents the legacy version of this plugin that we plan to remove on the
next version.
## When should I use it?
:::tip
Not sure which uploader is best for you? Read
“[Choosing the uploader you need](/docs/guides/choosing-uploader)”.
:::
:::warning
This plugin is deprecated, you should switch to using the
[modern version of this plugin](/docs/aws-s3-multipart).
:::
You can use this plugin when you prefer a _client-to-storage_ over a
_client-to-server-to-storage_ (such as [Transloadit](/docs/transloadit) or
[Tus](/docs/tus)) setup. This may in some cases be preferable, for instance, to
reduce costs or the complexity of running a server and load balancer with
[Tus](/docs/tus).
This plugin can be used with AWS S3, DigitalOcean Spaces, Google Cloud Storage,
or any S3-compatible provider. Although all S3-compatible providers are
supported, we dont test against them, this plugin was developed against S3 so a
small risk is involved in using the others.
`@uppy/aws-s3` is best suited for small files and/or lots of files. If you are
planning to upload mostly large files (100&nbsp;MB+), consider using
[`@uppy/aws-s3-multipart`](/docs/aws-s3-multipart).
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/aws-s3
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/aws-s3
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, AwsS3 } from "{{UPPY_JS_URL}}"
new Uppy().use(AwsS3, { /* see options */ })
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
A quick overview of the complete API.
```js {10} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import AwsS3 from '@uppy/aws-s3';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
const uppy = new Uppy()
.use(Dashboard, { inline: true, target: 'body' })
.use(AwsS3, { companionUrl: 'http://companion.uppy.io' });
```
### With a AWS S3 bucket
To use this plugin with S3 we need to setup a bucket with the right permissions
and CORS settings.
S3 buckets do not allow public uploads for security reasons. To allow Uppy and
the browser to upload directly to a bucket, its CORS permissions need to be
configured.
CORS permissions can be found in the
[S3 Management Console](https://console.aws.amazon.com/s3/home). Click the
bucket that will receive the uploads, then go into the `Permissions` tab and
select the `CORS configuration` button. A JSON document will be shown that
defines the CORS configuration. (AWS used to use XML but now only allow JSON).
More information about the
[S3 CORS format here](https://docs.amazonaws.cn/en_us/AmazonS3/latest/userguide/ManageCorsUsing.html).
The configuration required for Uppy and Companion is this:
```json
[
{
"AllowedOrigins": ["https://my-app.com"],
"AllowedMethods": ["GET", "POST"],
"MaxAgeSeconds": 3000,
"AllowedHeaders": [
"Authorization",
"x-amz-date",
"x-amz-content-sha256",
"content-type"
]
},
{
"AllowedOrigins": ["*"],
"AllowedMethods": ["GET"],
"MaxAgeSeconds": 3000
}
]
```
A good practice is to use two CORS rules: one for viewing the uploaded files,
and one for uploading files. This is done above where the first object in the
array defines the rules for uploading, and the second for viewing. The example
above **makes files publicly viewable**. You can change it according to your
needs.
If you are using an IAM policy to allow access to the S3 bucket, the policy must
have at least the `s3:PutObject` and `s3:PutObjectAcl` permissions scoped to the
bucket in question. In-depth documentation about CORS rules is available on the
[AWS documentation site](https://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html).
### With a DigitalOcean Spaces bucket
:::tip
Checkout the
[DigitalOcean Spaces example](https://github.com/transloadit/uppy/tree/main/examples/digitalocean-spaces)
in the Uppy repository for a complete, runnable example.
:::
DigitalOcean Spaces is S3-compatible so you only need to change the endpoint and
bucket. Make sure you have a `key` and `secret`. If not, refer to
“[How To Create a DigitalOcean Space and API Key](https://www.digitalocean.com/community/tutorials/how-to-create-a-digitalocean-space-and-api-key)”.
When using [Companion](/docs/companion) as standalone, you can set these as
environment variables:
```bash
export COMPANION_AWS_KEY="xxx"
export COMPANION_AWS_SECRET="xxx"
export COMPANION_AWS_REGION="us-east-1"
export COMPANION_AWS_ENDPOINT="https://{region}.digitaloceanspaces.com"
export COMPANION_AWS_BUCKET="my-space-name"
```
The `{region}` string will be replaced by the contents of the
`COMPANION_AWS_REGION` environment variable.
When using [Companion](/docs/companion) as an Express integration, configure the
`s3` options:
```js
const options = {
s3: {
key: 'xxx',
secret: 'xxx',
bucket: 'my-space-name',
region: 'us-east-1',
endpoint: 'https://{region}.digitaloceanspaces.com',
},
};
```
### With a Google Cloud Storage bucket
For the `@uppy/aws-s3` plugin to be able to upload to a GCS bucket, it needs the
Interoperability setting enabled. You can enable the Interoperability setting
and
[generate interoperable storage access keys](https://cloud.google.com/storage/docs/migrating#keys)
by going to [Google Cloud Storage](https://console.cloud.google.com/storage) »
Settings » Interoperability. Then set the environment variables for Companion
like this:
```bash
export COMPANION_AWS_ENDPOINT="https://storage.googleapis.com"
export COMPANION_AWS_BUCKET="YOUR-GCS-BUCKET-NAME"
export COMPANION_AWS_KEY="GOOGxxxxxxxxx" # The Access Key
export COMPANION_AWS_SECRET="YOUR-GCS-SECRET" # The Secret
```
You do not need to configure the region with GCS.
You also need to configure CORS with their HTTP API. If you havent done this
already, see
[Configuring CORS on a Bucket](https://cloud.google.com/storage/docs/configuring-cors#Configuring-CORS-on-a-Bucket)
in the GCS documentation, or follow the steps below to do it using Googles API
playground.
The JSON format consists of an array of CORS configuration objects. For
instance:
```json
{
"cors": [
{
"origin": ["https://my-app.com"],
"method": ["GET", "POST"],
"maxAgeSeconds": 3000
},
{
"origin": ["*"],
"method": ["GET"],
"maxAgeSeconds": 3000
}
]
}
```
When using presigned `PUT` uploads, replace the `"POST"` method by `"PUT"` in
the first entry.
If you have the [gsutil](https://cloud.google.com/storage/docs/gsutil)
command-line tool, you can apply this configuration using the
[gsutil cors](https://cloud.google.com/storage/docs/configuring-cors#configure-cors-bucket)
command.
```bash
gsutil cors set THAT-FILE.json gs://BUCKET-NAME
```
Otherwise, you can manually apply it through the OAuth playground:
1. Get a temporary API token from the
[Google OAuth2.0 playground](https://developers.google.com/oauthplayground/)
2. Select the `Cloud Storage JSON API v1` » `devstorage.full_control` scope
3. Press `Authorize APIs` and allow access
4. Click `Step 3 - Configure request to API`
5. Configure it as follows:
1. HTTP Method: PATCH
2. Request URI: `https://www.googleapis.com/storage/v1/b/YOUR_BUCKET_NAME`
3. Content-Type: application/json (should be the default)
4. Press `Enter request body` and input your CORS configuration
6. Press `Send the request`.
### Use with your own server
The recommended approach is to integrate `@uppy/aws-s3` with your own server.
You will need to do the following things:
1. Setup a bucket
2. Create endpoints in your server. You can create them as edge functions (such
as AWS Lambdas), inside Next.js as an API route, or wherever your server runs
- `POST` > `/uppy/s3`: get upload parameters
3. [Setup Uppy](https://github.com/transloadit/uppy/blob/main/examples/aws-nodejs/public/index.html)
### Use with Companion
[Companion](/docs/companion) has S3 routes built-in for a plug-and-play
experience with Uppy.
:::caution
Generally its better for access control, observability, and scaling to
integrate `@uppy/aws-s3` with your own server. You may want to use
[Companion](/docs/companion) for creating, signing, and completing your S3
uploads if you already need Companion for remote files (such as from Google
Drive). Otherwise its not worth the hosting effort.
:::
```js {10} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import AwsS3 from '@uppy/aws-s3';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
const uppy = new Uppy.use(Dashboard, { inline: true, target: 'body' }).use(
AwsS3,
{ companionUrl: 'http://companion.uppy.io' },
);
```
## Options
The `@uppy/aws-s3` plugin has the following configurable options:
#### `id`
A unique identifier for this plugin (`string`, default: `'AwsS3'`).
#### `companionUrl`
Companion instance to use for signing S3 uploads (`string`, default: `null`).
#### `companionHeaders`
Custom headers that should be sent along to [Companion](/docs/companion) on
every request (`Object`, default: `{}`).
#### `allowedMetaFields`
Pass an array of field names to limit the metadata fields that will be added to
upload as query parameters (`Array`, default: `null`).
- Set this to `['name']` to only send the `name` field.
- Set this to `null` (the default) to send _all_ metadata fields.
- Set this to an empty array `[]` to not send any fields.
#### `getUploadParameters(file)`
:::note
When using [Companion][companion docs] to sign S3 uploads, do not define this
option.
:::
A function that returns upload parameters for a file (`Promise`, default:
`null`).
Parameters should be returned as an object, or as a `Promise` that fulfills with
an object, with keys `{ method, url, fields, headers }`.
- The `method` field is the HTTP method to be used for the upload. This should
be one of either `PUT` or `POST`, depending on the type of upload used.
- The `url` field is the URL to which the upload request will be sent. When
using a presigned PUT upload, this should be the URL to the S3 object with
signing parameters included in the query string. When using a POST upload with
a policy document, this should be the root URL of the bucket.
- The `fields` field is an object with form fields to send along with the upload
request. For presigned PUT uploads, this should be left empty.
- The `headers` field is an object with request headers to send along with the
upload request. When using a presigned PUT upload, its a good idea to provide
`headers['content-type']`. That will make sure that the request uses the same
content-type that was used to generate the signature. Without it, the browser
may decide on a different content-type instead, causing S3 to reject the
upload.
#### `timeout`
When no upload progress events have been received for this amount of
milliseconds, assume the connection has an issue and abort the upload (`number`,
default: `30_000`).
This is passed through to [XHRUpload](/docs/xhr-upload#timeout-30-1000); see its
documentation page for details. Set to `0` to disable this check.
#### `limit`
Limit the amount of uploads going on at the same time (`number`, default: `5`).
Setting this to `0` means no limit on concurrent uploads, but we recommend a
value between `5` and `20`.
#### `getResponseData(responseText, response)`
:::note
This is an advanced option intended for use with _almost_ S3-compatible storage
solutions.
:::
Customize response handling once an upload is completed. This passes the
function through to @uppy/xhr-upload, see its
[documentation](https://uppy.io/docs/xhr-upload/#getResponseData-responseText-response)
for API details.
This option is useful when uploading to an S3-like service that doesnt reply
with an XML document, but with something else such as JSON.
#### `locale: {}`
```js
export default {
strings: {
timedOut: 'Upload stalled for %{seconds} seconds, aborting.',
},
};
```
## Frequently Asked Questions
### How can I generate a presigned URL server-side?
The `getUploadParameters` function can return a `Promise`, so upload parameters
can be prepared server-side. That way, no private keys to the S3 bucket need to
be shared on the client. For example, there could be a PHP server endpoint that
prepares a presigned URL for a file:
```js
uppy.use(AwsS3, {
getUploadParameters(file) {
// Send a request to our PHP signing endpoint.
return fetch('/s3-sign.php', {
method: 'post',
// Send and receive JSON.
headers: {
accept: 'application/json',
'content-type': 'application/json',
},
body: JSON.stringify({
filename: file.name,
contentType: file.type,
}),
})
.then((response) => {
// Parse the JSON response.
return response.json();
})
.then((data) => {
// Return an object in the correct shape.
return {
method: data.method,
url: data.url,
fields: data.fields,
// Provide content type header required by S3
headers: {
'Content-Type': file.type,
},
};
});
},
});
```
See either the
[aws-nodejs](https://github.com/transloadit/uppy/tree/HEAD/examples/aws-nodejs)
or [aws-php](https://github.com/transloadit/uppy/tree/HEAD/examples/aws-php)
examples in the uppy repository for a demonstration of how to implement handling
of presigned URLs on both the server-side and client-side.
### How can I retrieve the presigned parameters of the uploaded file?
Once the file is uploaded, its possible to retrieve the parameters that were
generated in `getUploadParameters(file)` via the `file.meta` field:
```js
uppy.on('upload-success', (file, data) => {
const s3Key = file.meta['key']; // the S3 object key of the uploaded file
});
```
[companion docs]: /docs/companion

View file

@ -0,0 +1,684 @@
---
sidebar_position: 1
slug: /transloadit
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Transloadit
The `@uppy/transloadit` plugin can be used to upload files directly to
[Transloadit](https://transloadit.com/) for all kinds of processing, such as
transcoding video, resizing images, zipping/unzipping, [and much
more][transloadit-services].
## When should I use it?
:::tip
Not sure which uploader is best for you? Read
“[Choosing the uploader you need](/docs/guides/choosing-uploader)”.
:::
Transloadits strength is versatility. By doing video, audio, images, documents,
and more, you only need one vendor for [all your file processing
needs][transloadit-services]. The `@uppy/transloadit` plugin directly uploads to
Transloadit so you only have to worry about creating a
[Template][transloadit-concepts]. Transloadit accepts the files, processes
according to the instructions in the Template, and stores the results in storage
of your choosing, such as a self-owned S3 bucket. The Transloadit plugin uses
[Tus](/docs/tus) under the hood so you dont have to sacrifice reliable,
resumable uploads.
You should use `@uppy/transloadit` if you dont want to host your own Tus or
Companion servers, (optionally) need file processing, and store it in the
service (such as S3 or GCS) of your liking. All with minimal effort.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/transloadit
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/transloadit
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Transloadit } from "{{UPPY_JS_URL}}"
new Uppy().use(Transloadit, { /* see options */ })
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
A quick overview of the complete API.
```js {10-17} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import Transloadit from '@uppy/transloadit';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
const uppy = new Uppy()
.use(Dashboard, { inline: true, target: 'body' })
.use(Transloadit, {
assemblyOptions: {
params: {
auth: { key: 'your-transloadit-key' },
template_id: 'your-template-id',
},
},
});
// Optionally listen to events
uppy.on('transloadit:assembly-created', (assembly, fileIDs) => {});
uppy.on('transloadit:upload', (file, assembly) => {});
uppy.on('transloadit:assembly-executing', (assembly) => {});
uppy.on('transloadit:result', (stepName, result, assembly) => {});
uppy.on('transloadit:complete', (assembly) => {});
```
### Use with Companion
:::note
All [Transloadit plans](https://transloadit/pricing/) come with a hosted version
of Companion.
:::
You can use this plugin together with Transloadits hosted Companion service to
let your users import files from third party sources across the web. To do so
each provider plugin must be configured with Transloadits Companion URLs:
```js
import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit';
import Dropbox from '@uppy/dropbox';
uppy.use(Dropbox, {
companionUrl: COMPANION_URL,
companionAllowedHosts: COMPANION_ALLOWED_HOSTS,
});
```
This will already work. Transloadits OAuth applications are used to
authenticate your users by default. Your users will be asked to provide
Transloadit access to their files. Since your users are probably not aware of
Transloadit, this may be confusing or decrease trust. You may also hit rate
limits, because the OAuth application is shared between everyone using
Transloadit.
To solve that, you can use your own OAuth keys with Transloadits hosted
Companion servers by using Transloadit Template Credentials. [Create a Template
Credential][template-credentials] on the Transloadit site. Select “Companion
OAuth” for the service, and enter the key and secret for the provider you want
to use. Then you can pass the name of the new credentials to that provider:
```js
import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit';
import Dropbox from '@uppy/dropbox';
uppy.use(Dropbox, {
companionUrl: COMPANION_URL,
companionAllowedHosts: COMPANION_ALLOWED_HOSTS,
companionKeysParams: {
key: 'YOUR_TRANSLOADIT_API_KEY',
credentialsName: 'my_companion_dropbox_creds',
},
});
```
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'Transloadit'`).
#### `service`
The Transloadit API URL to use (`string`, default:
`https://api2.transloadit.com`).
The default will try to route traffic efficiently based on the location of your
users. You could for instance set it to `https://api2-us-east-1.transloadit.com`
if you need the traffic to stay inside a particular region.
#### `limit`
Limit the amount of uploads going on at the same time (`number`, default: `20`).
Setting this to `0` means no limit on concurrent uploads, but we recommend a
value between `5` and `20`. This option is passed through to the
[`@uppy/tus`](/docs/tus) plugin, which this plugin uses internally.
#### `assemblyOptions`
Configure the
[Assembly Instructions](https://transloadit.com/docs/topics/assembly-instructions/),
the fields to send along to the assembly, and authentication
(`object | function`, default: `null`).
The object you can pass or return from a function has this structure:
```js
{
params: {
auth: { key: 'key-from-transloadit' },
template_id: 'id-from-transloadit',
steps: {
// Overruling Template at runtime
},
notify_url: 'https://your-domain.com/assembly-status',
},
signature: 'generated-signature',
fields: {
// Dynamic or static fields to send along
},
}
```
- `params` is used to authenticate with Transloadit and using your desired
[template](https://transloadit.com/docs/topics/templates/).
- `auth.key` _(required)_ is your authentication key which you can find on the
“Credentials” page of your account.
- `template_id` _(required)_ is the unique identifier to use the right
template from your account.
- `steps` _(optional)_ can be used to
[overrule Templates at runtime](https://transloadit.com/docs/topics/templates/#overruling-templates-at-runtime).
A typical use case might be changing the storage path on the fly based on
the session user id. For most use cases, we recommend to let your Templates
handle dynamic cases (they can accept `fields` and execute arbitrary
JavaScript as well), and not pass in `steps` from a browser. The template
editor also has extra validations and context.
- `notify_url` _(optional)_ is a pingback with the assembly status as JSON.
For instance, if you dont want to block the user experience by letting them
wait for your template to complete with
[`waitForEncoding`](#waitForEncoding), but you do want to want to
asynchrounously have an update, you can provide an URL which will be
“pinged” with the assembly status.
- `signature` _(optional, but recommended)_ is a cryptographic signature to
provide further trust in unstrusted environments. Refer to
“[Signature Authentication”](https://transloadit.com/docs/topics/signature-authentication/)
for more information.
- `fields` _(optional)_ can be used to to send along key/value pairs, which can
be
[used dynamically in your template](https://transloadit.com/docs/topics/assembly-instructions/#form-fields-in-instructions).
<details>
<summary>Examples</summary>
**As a function**
A custom `assemblyOptions()` option should return an object or a promise for an
object.
```js
uppy.use(Transloadit, {
assemblyOptions(file) {
return {
params: {
auth: { key: 'TRANSLOADIT_AUTH_KEY_HERE' },
template_id: 'xyz',
},
fields: {
caption: file.meta.caption,
},
};
},
});
```
The `${fields.caption}` variable will be available in the Assembly spawned from
Template `xyz`. You can use this to dynamically watermark images for example.
`assemblyOptions()` may also return a Promise, so it could retrieve signed
Assembly parameters from a server. For example, assuming an endpoint
`/transloadit-params` that responds with a JSON object with
`{ params, signature }` properties:
```js
uppy.use(Transloadit, {
async assemblyOptions(file) {
const res = await fetch('/transloadit-params');
return response.json();
},
});
```
**As an object**
If you dont need to change anything dynamically, you can also pass an object
directly.
```js
uppy.use(Transloadit, {
assemblyOptions: {
params: { auth: { key: 'transloadit-key' } },
},
});
```
**Use with @uppy/form**
Combine the `assemblyOptions()` option with the [Form](/docs/form) plugin to
pass user input from a `<form>` to a Transloadit Assembly:
```js
// This will add form field values to each file's `.meta` object:
uppy.use(Form, { getMetaFromForm: true });
uppy.use(Transloadit, {
getAssemblyOptions(file) {
return {
params: {
/* ... */
},
// Pass through the fields you need:
fields: {
message: file.meta.message,
},
};
},
});
```
</details>
:::caution
When you go to production always make sure to set the `signature`. **Not using
[Signature Authentication](https://transloadit.com/docs/topics/signature-authentication/)
can be a security risk**. Signature Authentication is a security measure that
can prevent outsiders from tampering with your Assembly Instructions. While
Signature Authentication is not implemented (yet), we recommend to disable
`allow_steps_override` in your Templates to avoid outsiders being able to pass
in any Instructions and storage targets on your behalf.
:::
#### `waitForEncoding`
Wait for the template to finish, rather than only the upload, before marking the
upload complete (`boolean`, default: `false`).
- When `false`, the Assemblies will complete (or error) in the background but
Uppy wont know or care about it. You may have to let Transloadit ping you via
a `notify_url` and asynchronously inform your user (email, in-app
notification).
- When `true`, the Transloadit plugin waits for Assemblies to complete before
the files are marked as completed. This means users have to wait for a
potentially long time, depending on how complicated your Assembly instructions
are. But, you can receive the final status and transcoding results on the
client side with less effort.
When this is enabled, you can listen for the
[`transloadit:result`](#transloaditresult) and
[`transloadit:complete`](#transloaditcomplete) events.
#### `waitForMetadata`
Wait for Transloadits backend to catch early errors, not the entire Assembly to
complete. (`boolean`, default: `false`)
When set to `true`, the Transloadit plugin waits for Transloadits backend to
extract metadata from all the uploaded files. This is mostly handy if you want
to have a quick user experience (so your users dont necessarily need to wait
for all the encoding to complete), but you do want to let users know about some
types of errors that can be caught early on, like file format issues.
You you can listen for the [`transloadit:upload`](#transloaditupload) event when
this or `waitForEncoding` is enabled.
#### `importFromUploadURLs`
Allow another plugin to upload files, and then import those files into the
Transloadit Assembly (`boolean`, default: `false`).
When enabling this option, Transloadit will _not_ configure the Tus plugin to
upload to Transloadit. Instead, a separate upload plugin must be used. Once the
upload completes, the Transloadit plugin adds the uploaded file to the Assembly.
For example, to upload files to an S3 bucket and then transcode them:
```js
uppy.use(AwsS3, {
getUploadParameters(file) {
return {
/* upload parameters */
};
},
});
uppy.use(Transloadit, {
importFromUploadURLs: true,
assemblyOptions: {
params: {
auth: { key: 'YOUR_API_KEY' },
template_id: 'YOUR_TEMPLATE_ID',
},
},
});
```
Tranloadit will download the files and expose them to your Template as
`:original`, as if they were directly uploaded from the Uppy client.
:::note
For this to work, the upload plugin must assign a publicly accessible
`uploadURL` property to the uploaded file object. The Tus and S3 plugins both do
this automatically, but you must configure your S3 bucket to have publicly
readable objects. For the XHRUpload plugin, you may have to specify a custom
`getResponseData` function.
:::
#### `alwaysRunAssembly`
Always create and run an Assembly when `uppy.upload()` is called, even if no
files were selected (`boolean`, default: `false`).
This allows running Assemblies that do not receive files, but instead use a
robot like [`/s3/import`](https://transloadit.com/docs/transcoding/#s3-import)
to download the files from elsewhere, for example, for a bulk transcoding job.
#### `locale`
```js
export default {
strings: {
// Shown while Assemblies are being created for an upload.
creatingAssembly: 'Preparing upload...',
// Shown if an Assembly could not be created.
creatingAssemblyFailed: 'Transloadit: Could not create Assembly',
// Shown after uploads have succeeded, but when the Assembly is still executing.
// This only shows if `waitForMetadata` or `waitForEncoding` was enabled.
encoding: 'Encoding...',
},
};
```
#### `clientName`
Append a custom client name to the `Transloadit-Client` header field when
creating an Assembly (`string`, default: `null`).
The `Transloadit-Client` header includes by default information about the used
SDK and is included in the Assembly Status under the `transloadit_client`
property. By providing a value, such as `homepage-file-uploader`, you can
identify the client and SDK that created a given Assembly.
<details>
<summary>Deprecated options</summary>
These options have been deprecated in favor of
[`assemblyOptions`](#assemblyoptions), which we now recommend for all use cases.
You can still use these options, but they will be removed in the next major
version.
#### `getAssemblyOptions`
This function behaves the same as passing a function to
[`assemblyOptions`](#assemblyoptions).
#### `params`
The Assembly parameters to use for the upload (`object`, default: `null`) See
the Transloadit documentation on
[Assembly Instructions](https://transloadit.com/docs/#14-assembly-instructions)
for further information.
The `auth.key` Assembly parameter is required. You can also use the `steps` or
`template_id` options here as described in the Transloadit documentation.
```js
uppy.use(Transloadit, {
params: {
auth: { key: 'YOUR_TRANSLOADIT_KEY' },
steps: {
encode: {
robot: '/video/encode',
use: {
steps: [':original'],
fields: ['file_input_field2'],
},
preset: 'iphone',
},
},
},
});
```
#### `signature`
An optional signature for the Assembly parameters. See the Transloadit
documentation on
[Signature Authentication](https://transloadit.com/docs/#26-signature-authentication)
for further information.
If a `signature` is provided, `params` should be a JSON string instead of a
JavaScript object, as otherwise the generated JSON in the browser may be
different from the JSON string that was used to generate the signature.
#### `fields`
An object of form fields to send along to the Assembly. Keys are field names,
and values are field values. See also the Transloadit documentation on
[Form Fields In Instructions](https://transloadit.com/docs/#23-form-fields-in-instructions).
```js
uppy.use(Transloadit, {
// ...
fields: {
message: 'This is a form field',
},
});
```
You can also pass an array of field names to send global or file metadata along
to the Assembly. Global metadata is set using the
[`meta` option](/docs/uppy/#meta) in the Uppy constructor, or using the
[`setMeta` method](/docs/uppy/#uppy-setMeta-data). File metadata is set using
the [`setFileMeta`](/docs/uppy/#uppy-setFileMeta-fileID-data) method. The
[Form](/docs/form) plugin also sets global metadata based on the values of
`<input />`s in the form, providing a handy way to use values from HTML form
fields:
```js
uppy.use(Form, { target: 'form#upload-form', getMetaFromForm: true });
uppy.use(Transloadit, {
fields: ['field_name', 'other_field_name'],
params: {
/* ... */
},
});
```
Form fields can also be computed dynamically using custom logic, by using the
[`getAssemblyOptions(file)`](/docs/transloadit/#getAssemblyOptions-file) option.
</details>
### Static exports
#### `COMPANION_URL`
The main endpoint for Transloadits hosted companions. You can use this constant
in remote provider options, like so:
```js
import Dropbox from '@uppy/dropbox';
import { COMPANION_URL } from '@uppy/transloadit';
uppy.use(Dropbox, {
companionUrl: COMPANION_URL,
});
```
When using `COMPANION_URL`, you should also configure
[`companionAllowedHosts`](#companion_allowed_hosts).
The value of this constant is `https://api2.transloadit.com/companion`. If you
are using a custom [`service`](#service) option, you should also set a custom
host option in your provider plugins, by taking a Transloadit API url and
appending `/companion`:
```js
uppy.use(Dropbox, {
companionUrl: 'https://api2-us-east-1.transloadit.com/companion',
});
```
#### `COMPANION_ALLOWED_HOSTS`
A RegExp pattern matching Transloadits hosted companion endpoints. The pattern
is used in remote provider `companionAllowedHosts` options, to make sure that
third party authentication messages cannot be faked by an attackers page but
can only originate from Transloadits servers.
Use it whenever you use `companionUrl: COMPANION_URL`, like so:
```js
import Dropbox from '@uppy/dropbox';
import { COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit';
uppy.use(Dropbox, {
companionAllowedHosts: COMPANION_ALLOWED_HOSTS,
});
```
The value of this constant covers _all_ Transloadits Companion servers, so it
does not need to be changed if you are using a custom [`service`](#service)
option. But, if you are not using the Transloadit Companion servers at
`*.transloadit.com`, make sure to set the `companionAllowedHosts` option to
something that matches what you do use.
### Events
#### `transloadit:assembly-created`
Fired when an Assembly is created.
**Parameters**
- `assembly` - The initial [Assembly Status][assembly-status].
- `fileIDs` - The IDs of the files that will be uploaded to this Assembly.
```js
uppy.on('transloadit:assembly-created', (assembly, fileIDs) => {
console.group('Created', assembly.assembly_id, 'for files:');
for (const id of fileIDs) {
console.log(uppy.getFile(id).name);
}
console.groupEnd();
});
```
#### `transloadit:upload`
Fired when Transloadit has received an upload. Requires
[`waitForMetadata`](#waitformetadata) to be set.
**Parameters**
- `file` - The Transloadit file object that was uploaded.
- `assembly` - The [Assembly Status][assembly-status] of the Assembly to which
the file was uploaded.
#### `transloadit:assembly-executing`
Fired when Transloadit has received all uploads, and is executing the Assembly.
**Parameters**
- `assembly` - The
[Assembly Status](https://transloadit.com/docs/api/#assembly-status-response)
of the Assembly that is executing.
#### `transloadit:result`
Fired when a result came in from an Assembly. Requires
[`waitForEncoding`](#waitforencoding) to be set.
**Parameters**
- `stepName` - The name of the Assembly step that generated this result.
- `result` - The result object from Transloadit. This result object has one more
property, namely `localId`. This is the ID of the file in Uppys local state,
and can be used with `uppy.getFile(id)`.
- `assembly` - The [Assembly Status][assembly-status] of the Assembly that
generated this result.
```js
uppy.on('transloadit:result', (stepName, result) => {
const file = uppy.getFile(result.localId);
document.body.appendChild(html`
<div>
<h2>From ${file.name}</h2>
<a href=${result.ssl_url}> View </a>
</div>
`);
});
```
#### `transloadit:complete`
Fired when an Assembly completed. Requires [`waitForEncoding`](#waitForEncoding)
to be set.
**Parameters**
- `assembly` - The final [Assembly Status][assembly-status] of the completed
Assembly.
```js
uppy.on('transloadit:complete', (assembly) => {
// Could do something fun with this!
console.log(assembly.results);
});
```
## Frequently Asked Questions
### Accessing the assembly when an error occurred
If an error occurs when an Assembly has already started, you can find the
Assembly Status on the error objects `assembly` property.
```js
uppy.on('error', (error) => {
if (error.assembly) {
console.log(`Assembly ID ${error.assembly.assembly_id} failed!`);
console.log(error.assembly);
}
});
```
### Assembly behavior when Uppy is closed
When integrating `@uppy/transloadit` with `@uppy/dashboard`, closing the
dashboard will result in continuing assemblies on the server. When the user
manually cancels the upload any running assemblies will be cancelled.
[assembly-status]: https://transloadit.com/docs/api/#assembly-status-response
[template-credentials]:
https://transloadit.com/docs/#how-to-create-template-credentials
[transloadit-services]: https://transloadit.com/services/
[transloadit-concepts]: https://transloadit.com/docs/getting-started/concepts/

308
docs/uploader/tus.mdx Normal file
View file

@ -0,0 +1,308 @@
---
sidebar_position: 2
slug: /tus
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Tus
The `@uppy/tus` plugin brings resumable file uploading with [Tus](http://tus.io)
to Uppy by wrapping the [`tus-js-client`][].
## When should I use it?
:::tip
Not sure which uploader is best for you? Read
“[Choosing the uploader you need](/docs/guides/choosing-uploader)”.
:::
[Tus][tus] is an open protocol for resumable uploads built on HTTP. This means
accidentally closing your tab or losing connection lets you continue, for
instance, your 10GB upload instead of starting all over.
Tus supports any language, any platform, and any network. It requires a client
and server integration to work. You can checkout the client and server
[implementations][] to find the server in your preferred language. You can store
files on the Tus server itself, but you can also use service integrations (such
as S3) to store files externally. If you dont want to host your own server, see
“[Are there hosted Tus servers?](#are-there-hosted-tus-servers)”.
If you want reliable, resumable uploads: use `@uppy/tus` to connect to your Tus
server in a few lines of code.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/tus
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/tus
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Tus } from "{{UPPY_JS_URL}}"
new Uppy().use(Tus, { endpoint: 'https://tusd.tusdemo.net/files' })
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
A quick overview of the complete API.
```js {10} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import Tus from '@uppy/tus';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
new Uppy()
.use(Dashboard, { inline: true, target: 'body' })
.use(Tus, { endpoint: 'https://tusd.tusdemo.net/files/' });
```
## API
### Options
:::info
All options are passed to `tus-js-client` and we document the ones here that are
required, added, or changed. This means you can also pass functions like
[`onAfterResponse`](https://github.com/tus/tus-js-client/blob/master/docs/api.md#onafterresponse).
We recommended taking a look at the
[API reference](https://github.com/tus/tus-js-client/blob/master/docs/api.md)
from `tus-js-client` to know what is supported.
:::
#### `id`
A unique identifier for this plugin (`string`, default: `'Tus'`).
#### `endpoint`
URL of the tus server (`string`, default: `null`).
#### `headers`
An object or function returning an object with HTTP headers to send along
requests (`object | function`, default: `null`).
Keys are header names, values are header values.
```js
const headers = {
authorization: `Bearer ${window.getCurrentUserToken()}`,
};
```
Header values can also be derived from file data by providing a function. The
function receives an [Uppy file][] and must return an object where the keys are
header names, and values are header values.
```js
const headers = (file) => {
return {
authorization: `Bearer ${window.getCurrentUserToken()}`,
expires: file.meta.expires,
};
};
```
#### `chunkSize`
A number indicating the maximum size of a `PATCH` request body in bytes
(`number`, default: `Infinity`). Note that this option only affects local
browser uploads. If you need a max chunk size for remote (Companion) uploads,
you must set the `chunkSize` Companion option as well.
:::caution
Do not set this value unless you are forced to. The two valid reasons are
described in the
[`tus-js-client` docs](https://github.com/tus/tus-js-client/blob/master/docs/api.md#chunksize).
:::
#### `withCredentials`
Configure the requests to send Cookies using the
[`xhr.withCredentials`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials)
property (`boolean`, default: `false`).
The remote server must accept CORS and credentials.
#### `retryDelays`
When uploading a chunk fails, automatically try again after the defined
millisecond intervals (`Array<number>`, default: `[0, 1000, 3000, 5000]`).
By default, we first retry instantly; if that fails, we retry after 1 second; if
that fails, we retry after 3 seconds, etc.
Set to `null` to disable automatic retries, and fail instantly if any chunk
fails to upload.
#### `onBeforeRequest(req, file)`
Behaves like the
[`onBeforeRequest`](https://github.com/tus/tus-js-client/blob/master/docs/api.md#onbeforerequest)
function from `tus-js-client` but with the added `file` argument.
#### `onShouldRetry: (err, retryAttempt, options, next)`
When an upload fails `onShouldRetry` is called with the error and the default
retry logic as the last argument (`function`).
The default retry logic is an
[exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff)
algorithm triggered on HTTP 429 (Too Many Requests) errors. Meaning if your
server (or proxy) returns HTTP 429 because its being overloaded, @uppy/tus will
find the ideal sweet spot to keep uploading without overloading.
If you want to extend this functionality, for instance to retry on unauthorized
requests (to retrieve a new authentication token):
```js
import Uppy from '@uppy/core';
import Tus from '@uppy/tus';
new Uppy().use(Tus, {
endpoint: '',
async onBeforeRequest(req) {
const token = await getAuthToken();
req.setHeader('Authorization', `Bearer ${token}`);
},
onShouldRetry(err, retryAttempt, options, next) {
if (err?.originalResponse?.getStatus() === 401) {
return true;
}
return next(err);
},
async onAfterResponse(req, res) {
if (res.getStatus() === 401) {
await refreshAuthToken();
}
},
});
```
#### `allowedMetaFields`
Pass an array of field names to limit the metadata fields that will be added to
uploads as
[Tus Metadata](https://tus.io/protocols/resumable-upload.html#upload-metadata)
(`Array`, default: `null`).
- Set this to `['name']` to only send the `name` field.
- Set this to `null` (the default) to send _all_ metadata fields.
- Set this to an empty array `[]` to not send any fields.
#### `limit`
Limit the amount of uploads going on at the same time (`number`, default: `20`).
Setting this to `0` means no limit on concurrent uploads (not recommended).
## Frequently Asked Questions
:::info
The Tus website has extensive [FAQ section](https://tus.io/faq.html), we
recommend taking a look there as well if something is unclear.
:::
### How is file meta data stored?
Tus uses unique identifiers for the file names to prevent naming collisions. To
still keep the meta data in place, Tus also uploads an extra `.info` file with
the original file name and other meta data:
```json
{
"ID": "00007a99d16d4eeb5a3e3c080b6f69da+JHZavdqPSK4VMtarg2yYcNiP8t_kDjN51lBYMJdEyr_wqEotVl8ZBRBSTnWKWenZBwHvbLNz5tQXYp2N7Vdol.04ysQAuw__suTJ4IsCljj0rjyWA6LvV4IwF5P2oom2",
"Size": 1679852,
"SizeIsDeferred": false,
"Offset": 0,
"MetaData": {
"filename": "cat.jpg",
"filetype": "image/jpeg"
},
"IsPartial": false,
"IsFinal": false,
"PartialUploads": null,
"Storage": {
"Bucket": "your-bucket",
"Key": "some-key",
"Type": "s3store"
}
}
```
### How do I change files before sending them?
If you want to change the file names, you want to do that in
[`onBeforeFileAdded`](/docs/uppy#onbeforefileaddedfile-files).
If you want to send extra headers with the request, use [`headers`](#headers) or
[`onBeforeRequest`](#onbeforerequestreq-file).
### How do I change (or move) files after sending them?
If you want to preserve files names, extract meta data, or move files to a
different place you generally can with hooks or events. It depends on the Tus
server you use how its done exactly. [`tusd`][], for instance, exposes
[hooks](https://github.com/tus/tusd/blob/master/docs/hooks.md) and
[`tus-node-server`](https://github.com/tus/tus-node-server) has
[events](https://github.com/tus/tus-node-server#events).
### Which server do you recommend?
[Transloadit](https://transloadit.com) runs [`tusd`][] in production, where it
serves millions of requests globally. So we recommend `tusd` as battle-tested
from our side, but other companies have had success with other
[implementations][] so it depends on your needs.
### Are there hosted Tus servers?
All [Transloadit plans](https://transloadit.com/pricing) come with a hosted
[`tusd`][] server. You dont have to do anything to leverage it, using
[`@uppy/transloadit`](/docs/transloadit) automatically uses Tus under the hood.
### Why Tus instead of directly uploading to AWS S3?
First: reliable, resumable uploads. This means accidentally closing your tab or
losing connection lets you continue, for instance, your 10GB upload instead of
starting all over.
Tus is also efficient with lots of files (such as 8K) and large files. Uploading
to AWS S3 directly from the client also introduces quite a bit of overhead, as
more requests are needed for the flow to work.
[`tus-js-client`]: https://github.com/tus/tus-js-client
[uppy file]: /docs/uppy#working-with-uppy-files
[tus]: https://tus.io/
[`tusd`]: https://github.com/tus/tusd
[implementations]: https://tus.io/implementations.html

399
docs/uploader/xhr.mdx Normal file
View file

@ -0,0 +1,399 @@
---
sidebar_position: 5
slug: /xhr-upload
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# XHR
The `@uppy/xhr-upload` plugin is for regular uploads to a HTTP server.
## When should I use it?
:::tip
Not sure which uploader is best for you? Read
“[Choosing the uploader you need](/docs/guides/choosing-uploader)”.
:::
When you have an existing HTTP server and you dont need Transloadit services or
want to run a [tus][] server. Note that its still possible to use [tus][]
without running an extra server by integrating tus into your existing one. For
instance, if you have a Node.js server (or server-side framework like Next.js)
you could integrate [tus-node-server][].
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/xhr-upload
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/xhr-upload
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, XHRUpload } from "{{UPPY_JS_URL}}"
new Uppy().use(XHRUpload, { endpoint: 'https://tusd.tusdemo.net/files' })
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
A quick overview of the complete API.
```js {10} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import XHR from '@uppy/xhr-upload';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
new Uppy()
.use(Dashboard, { inline: true, target: 'body' })
.use(XHR, { endpoint: 'https://your-domain.com/upload' });
```
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'XHRUpload'`).
#### `endpoint`
URL of the HTTP server (`string`, default: `null`).
#### `method`
Configures which HTTP method to use for the upload (`string`, default:
`'post'`).
#### `formData`
Configures whether to use a multipart form upload, using [FormData][]
(`boolean`, default: `true`).
This works similarly to using a `<form>` element with an `<input type="file">`
for uploads. When set to `true`, file metadata is also sent to the endpoint as
separate form fields. When set to `false`, only the file contents are sent.
#### `fieldName`
When [`formData`](#formData-true) is set to true, this is used as the form field
name for the file to be uploaded.
It defaults to `'files[]'` if `bundle` option is set to `true`, otherwise it
defaults to `'file'`.
#### `allowedMetaFields`
Pass an array of field names to limit the metadata fields that will be added to
upload.
- Set this to an empty array `[]` to not send any fields.
- Set this to `['name']` to only send the `name` field.
- Set this to `null` (the default) to send _all_ metadata fields.
If the [`formData`](#formData-true) option is set to false, `metaFields` is
ignored.
#### `headers`
An object containing HTTP headers to use for the upload request. Keys are header
names, values are header values.
```js
const headers = {
authorization: `Bearer ${window.getCurrentUserToken()}`,
};
```
Header values can also be derived from file data by providing a function. The
function receives an [Uppy file][] and must return an object where the keys are
header names, and values are header values.
```js
const headers = (file) => {
return {
authorization: `Bearer ${window.getCurrentUserToken()}`,
expires: file.meta.expires,
};
};
```
:::note
The function syntax is not available when [`bundle`](#bundle) is set to `true`.
:::
#### `bundle`
Send all files in a single multipart request (`boolean`, default: `false`).
All files will be appended to the provided `fieldName` field in the request.
:::caution
When `bundle` is set to `true`:
- [`formData`](#formData-true) must also be set to `true`.
- Uppy wont be able to bundle remote files (such as Google Drive) and will
throw an error in this case.
- Only [global uppy metadata](/docs/uppy/#meta) is sent to the endpoint.
Individual per-file metadata is ignored.
:::
To upload files on different fields, use
[`uppy.setFileState()`](/docs/uppy#uppy-setFileState-fileID-state) to set the
`xhrUpload.fieldName` property on the file:
```js
uppy.setFileState(fileID, {
xhrUpload: { fieldName: 'pic0' },
});
```
#### `validateStatus`
Check if the response was successful (`function`, default:
`(status, responseText, response) => boolean`).
- By default, responses with a 2xx HTTP status code are considered successful.
- When `true`, [`getResponseData()`](#getResponseData-responseText-response)
will be called and the upload will be marked as successful.
- When `false`, both
[`getResponseData()`](#getResponseData-responseText-response) and
[`getResponseError()`](#getResponseError-responseText-response) will be called
and the upload will be marked as unsuccessful.
##### Parameters
- The `statusCode` is the numeric HTTP status code returned by the endpoint.
- The `responseText` is the XHR endpoint response as a string.
- `response` is the [XMLHttpRequest][] object.
:::note
This option is only used for **local** uploads. Uploads from remote providers
like Google Drive or Instagram do not support this and will always use the
default.
:::
#### `getResponseData`
Extract the response data from the successful upload (`function`, default:
`(responseText, response) => void`).
- `responseText` is the XHR endpoint response as a string.
- `response` is the [XMLHttpRequest][] object.
JSON is handled automatically, so you should only use this if the endpoint
responds with a different format. For example, an endpoint that responds with an
XML document:
```js
function getResponseData(responseText, response) {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(responseText, 'text/xml');
return {
url: xmlDoc.querySelector('Location').textContent,
};
}
```
:::note
This response data will be available on the files `.response` property and will
be emitted in the [`upload-success`][uppy.upload-success] event.
:::
:::note
When uploading files from remote providers such as Dropbox or Instagram,
Companion sends upload response data to the client. This is made available in
the `getResponseData()` function as well. The `response` object from Companion
has some properties named after their [XMLHttpRequest][] counterparts.
:::
#### `getResponseError`
Extract the error from the failed upload (`function`, default:
`(responseText, response) => void`).
For example, if the endpoint responds with a JSON object containing a
`{ message }` property, this would show that message to the user:
```js
function getResponseError(responseText, response) {
return new Error(JSON.parse(responseText).message);
}
```
#### `responseUrlFieldName`
The field name containing the location of the uploaded file (`string`, default:
`'url'`).
This is returned by [`getResponseData()`](#getResponseData).
#### `timeout: 30 * 1000`
Abort the connection if no upload progress events have been received for this
milliseconds amount (`number`, default: `30_000`).
Note that unlike the [`XMLHttpRequest.timeout`][xhr.timeout] property, this is a
timer between progress events: the total upload can take longer than this value.
Set to `0` to disable this check.
#### `limit`
The maximum amount of files to upload in parallel (`number`, default: `5`).
#### `responseType`
The response type expected from the server, determining how the `xhr.response`
property should be filled (`string`, default: `'text'`).
The `xhr.response` property can be accessed in a custom
[`getResponseData()`](#getResponseData-responseText-response) callback. This
option sets the [`XMLHttpRequest.responseType`][xhr.responsetype] property. Only
`''`, `'text'`, `'arraybuffer'`, `'blob'` and `'document'` are widely supported
by browsers, so its recommended to use one of those.
#### `withCredentials`
Indicates whether cross-site Access-Control requests should be made using
credentials (`boolean`, default: `false`).
#### `locale: {}`
```js
export default {
strings: {
// Shown in the Informer if an upload is being canceled because it stalled for too long.
timedOut: 'Upload stalled for %{seconds} seconds, aborting.',
},
};
```
## Frequently Asked Questions
### How to send along meta data with the upload?
When using XHRUpload with [`formData: true`](#formData-true), file metadata is
sent along with each upload request. You can set metadata for a file using
[`uppy.setFileMeta(fileID, data)`](/docs/uppy#uppy-setFileMeta-fileID-data), or
for all files simultaneously using
[`uppy.setMeta(data)`](/docs/uppy#uppy-setMeta-data).
It may be useful to set metadata depending on some file properties, such as the
size. You can use the [`file-added`](/docs/uppy/#file-added) event and the
[`uppy.setFileMeta(fileID, data)`](/docs/uppy#uppy-setFileMeta-fileID-data)
method to do this:
```js
uppy.on('file-added', (file) => {
uppy.setFileMeta(file.id, {
size: file.size,
});
});
```
Now, a form field named `size` will be sent along to the
[`endpoint`](#endpoint-39-39) once the upload starts.
By default, all metadata is sent, including Uppys default `name` and `type`
metadata. If you do not want the `name` and `type` metadata properties to be
sent to your upload endpoint, you can use the [`metaFields`](#metaFields-null)
option to restrict the field names that should be sent.
```js
uppy.use(XHRUpload, {
// Only send our own `size` metadata field.
allowedMetaFields: ['size'],
});
```
### How to upload to a PHP server?
The XHRUpload plugin works similarly to a `<form>` upload. You can use the
`$_FILES` variable on the server to work with uploaded files. See the PHP
documentation on [Handling file uploads][php.file-upload].
The default form field for file uploads is `files[]`, which means you have to
access the `$_FILES` array as described in [Uploading many files][php.multiple]:
```php
<?php
// upload.php
$files = $_FILES['files'];
$file_path = $files['tmp_name'][0]; // temporary upload path of the first file
$file_name = $_POST['name']; // desired name of the file
move_uploaded_file($file_path, './img/' . basename($file_name)); // save the file in `img/`
```
Note how we are using `$_POST['name']` instead of `$my_file['name']`.
`$my_file['name']` has the original name of the file on the users device.
`$_POST['name']` has the `name` metadata value for the uploaded file, which can
be edited by the user using the [Dashboard](/docs/dashboard).
Set a custom `fieldName` to make working with the `$_FILES` array a bit less
convoluted:
```js
// app.js
uppy.use(XHRUpload, {
endpoint: '/upload.php',
fieldName: 'my_file',
});
```
```php
<?php
// upload.php
$my_file = $_FILES['my_file'];
$file_path = $my_file['tmp_name']; // temporary upload path of the file
$file_name = $_POST['name']; // desired name of the file
move_uploaded_file($file_path, $_SERVER['DOCUMENT_ROOT'] . '/img/' . basename($file_name)); // save the file at `img/FILE_NAME`
```
[formdata]: https://developer.mozilla.org/en-US/docs/Web/API/FormData
[xmlhttprequest]:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
[xhr.timeout]:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/timeout
[xhr.responsetype]:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType
[uppy.upload-success]: /docs/uppy/#upload-success
[uppy file]: /docs/uppy#working-with-uppy-files
[php.file-upload]: https://secure.php.net/manual/en/features.file-upload.php
[php.multiple]:
https://secure.php.net/manual/en/features.file-upload.multiple.php
[tus-node-server]: https://github.com/tus/tus-node-server
[tus]: https://tus.io/

1628
docs/uppy-core.mdx Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
{
"label": "User interfaces",
"position": 5
}

View file

@ -0,0 +1,753 @@
---
sidebar_position: 1
slug: /dashboard
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Dashboard
The all you need Dashboard — powerful, responsive, and pluggable. Kickstart your
uploading experience and gradually add more functionality. Add files from
[remote sources](/docs/companion), [edit images](/docs/image-editor),
[generate thumbnails](/docs/thumbnail-generator), and more.
Checkout [integrations](#integrations) for the full list of plugins you can
integrate.
:::tip
[Try out the live example with all plugins](/examples) or take it for a spin in
[CodeSandbox](https://codesandbox.io/s/uppy-dashboard-xpxuhd).
:::
## When should I use this?
There could be many reasons why you may want to use the Dashboard, but some
could be:
- when you need a battle tested plug-and-play uploading UI to save time.
- when your users need to add files from [remote sources](/docs/companion), such
[Google Drive](/docs/google-drive), [Dropbox](/docs/dropbox), and others.
- when you need to collect [meta data](#metafields) from your users per file.
- when your users want to take a picture with their [webcam](/docs/webcam) or
[capture their screen](/docs/screen-capture).
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/core @uppy/dashboard
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/core @uppy/dashboard
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Dashboard } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(Dashboard, { target: '#uppy', inline: true })
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
```js showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
new Uppy().use(Dashboard, { inline: true, target: '#uppy-dashboard' });
```
:::note
The `@uppy/dashboard` plugin includes CSS for the Dashboard itself, and the
various plugins used by the Dashboard, such as
([`@uppy/status-bar`](/docs/status-bar) and [`@uppy/informer`](/docs/informer)).
If you also use the `@uppy/status-bar` or `@uppy/informer` plugin directly, you
should not include their CSS files, but instead only use the one from the
`@uppy/dashboard` plugin.
:::
:::note
Styles for Provider plugins, like Google Drive and Instagram, are also bundled
with Dashboard styles. Styles for other plugins, such as `@uppy/url` and
`@uppy/webcam`, are not included. If you are using those, please see their docs
and make sure to include styles for them as well.
:::
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'Dashboard'`).
Plugins that are added by the Dashboard get unique IDs based on this ID, like
`'Dashboard:StatusBar'` and `'Dashboard:Informer'`.
#### `target`
Where to render the Dashboard (`string` or `Element`, default: `'body'`).
You can pass an element, class, or id as a string. Dashboard is rendered into
`body`, because its hidden by default and only opened as a modal when `trigger`
is clicked.
#### `inline`
Render the Dashboard as a modal or inline (`boolean`, default: `false`).
When `false`, Dashboard is opened by clicking on [`trigger`](#trigger). If
`inline: true`, Dashboard will be rendered into [`target`](#target) and fit
right in.
#### `trigger`
A CSS selector for a button that will trigger opening the Dashboard modal
(`string`, default: `null`).
Several buttons or links can be used, as long as they are selected using the
same selector (`.select-file-button`, for example).
#### `width`
Width of the Dashboard in pixels (`number`, default: `750`). Used when
`inline: true`.
#### `height`
Height of the Dashboard in pixels (`number`, default: `550`). Used when
`inline: true`.
#### `waitForThumbnailsBeforeUpload`
Whether to wait for all thumbnails from `@uppy/thumbnail-generator` to be ready
before starting the upload (`boolean`, default `false`).
If set to `true`, Thumbnail Generator will envoke Uppys internal processing
stage, displaying “Generating thumbnails...” message, and wait for
`thumbnail:all-generated` event, before proceeding to the uploading stage.
This is useful because Thumbnail Generator also adds EXIF data to images, and if
we wait until its done processing, this data will be available on the server
after the upload.
#### `showLinkToFileUploadResult`
Turn the file icon and thumbnail in the Dashboard into a link to the uploaded
file (`boolean`, default: `false`).
Please make sure to return the `url` key (or the one set via
`responseUrlFieldName`) from your server.
#### `showProgressDetails`
Show or hide progress details in the status bar (`boolean`, default: `false`).
By default, progress in Status Bar is shown as a percentage. If you would like
to also display remaining upload size and time, set this to `true`.
`showProgressDetails: false`: Uploading: 45%
`showProgressDetails: true`: Uploading: 45%・43 MB of 101 MB・8s left
#### `hideUploadButton`
Show or hide the upload button (`boolean`, default: `false`).
Use this if you are providing a custom upload button somewhere, and are using
the `uppy.upload()` API.
#### `hideRetryButton`
Hide the retry button in the status bar and on each individual file (`boolean`,
default: `false`).
Use this if you are providing a custom retry button somewhere and if you are
using the `uppy.retryAll()` or `uppy.retryUpload(fileID)` API.
#### `hidePauseResumeButton`
Hide the pause/resume button (for resumable uploads, via [tus](http://tus.io),
for example) in the status bar and on each individual file (`boolean`, default:
`false`).
Use this if you are providing custom cancel or pause/resume buttons somewhere,
and using the `uppy.pauseResume(fileID)` or `uppy.removeFile(fileID)` API.
#### `hideCancelButton`
Hide the cancel button in status bar and on each individual file (`boolean`,
default: `false`).
Use this if you are providing a custom retry button somewhere, and using the
`uppy.cancelAll()` API.
#### `hideProgressAfterFinish`
Hide the status bar after the upload has finished (`boolean`, default: `false`).
#### `doneButtonHandler`
This option is passed to the status bar and will render a “Done” button in place
of pause/resume/cancel buttons, once the upload/encoding is done. The behaviour
of this “Done” button is defined by this handler function, for instance to close
the file picker modals or clear the upload state.
This is what the Dashboard sets by default:
```js
const doneButtonHandler = () => {
this.uppy.cancelAll();
this.requestCloseModal();
};
```
Set to `null` to disable the “Done” button.
#### `showSelectedFiles`
Show the list of added files with a preview and file information (`boolean`,
default: `true`).
In case you are showing selected files in your own apps UI and want the Uppy
Dashboard to only be a picker, the list can be hidden with this option.
See also [`disableStatusBar`](#disablestatusbar) option, which can hide the
progress and upload button.
#### `showRemoveButtonAfterComplete`
Show the remove button on every file after a successful upload (`boolean`,
default: `false`).
Enabling this option only shows the remove `X` button in the Dashboard UI, but
to actually send a request you should listen to
[`file-removed`](https://uppy.io/docs/uppy/#file-removed) event and add your
logic there.
Example:
```js
uppy.on('file-removed', (file, reason) => {
if (reason === 'removed-by-user') {
sendDeleteRequestForFile(file);
}
});
```
For an implementation example, please see
[#2301](https://github.com/transloadit/uppy/issues/2301#issue-628931176).
#### `singleFileFullScreen`
When only one file is selected, its preview and meta information will be
centered and enlarged (`boolean`, default: `true`).
Often times Uppy used for photo / profile image uploads, or maybe a single
document. Then it makes sense to occupy the whole space of the available
Dashboard UI, giving the stage to this one file. This feature is automatically
disabled when Dashboard is small in height, since theres not enough room.
#### `note`
A string of text to be placed in the Dashboard UI (`string`, default: `null`).
This could for instance be used to explain any [`restrictions`](#restrictions)
that are put in place. For example:
`'Images and video only, 23 files, up to 1 MB'`.
#### `metaFields`
Create text or custom input fields for the user to fill in (`Array<Object>` or
`Function`, default: `null`).
This will be shown when a user clicks the “edit” button on that file.
:::note
The meta data will only be set on a file object if its entered by the user. If
the user doesnt edit a files metadata, it will not have default values;
instead everything will be `undefined`. If you want to set a certain meta field
to each file regardless of user actions, set
[`meta` in the Uppy constructor options](/docs/uppy/#meta).
:::
Each object can contain:
- `id`. The name of the meta field. This will also be used in CSS/HTML as part
of the `id` attribute, so its better to
[avoid using characters like periods, semicolons, etc](https://stackoverflow.com/a/79022).
- `name`. The label shown in the interface.
- `placeholder`. The text shown when no value is set in the field. (Not needed
when a custom render function is provided)
- `render: ({value, onChange, required, form}, h) => void` (optional). A
function for rendering a custom form element.
- `value` is the current value of the meta field
- `onChange: (newVal) => void` is a function saving the new value and `h` is
the `createElement` function from
[Preact](https://preactjs.com/guide/v10/api-reference#h--createelement).
- `required` is a boolean thats true if the field `id` is in the
`restrictedMetaFields` restriction
- `form` is the `id` of the associated `<form>` element.
- `h` can be useful when using Uppy from plain JavaScript, where you cannot
write JSX.
<details>
<summary>Example: meta fields configured as an `Array`</summary>
```js
uppy.use(Dashboard, {
trigger: '#pick-files',
metaFields: [
{ id: 'name', name: 'Name', placeholder: 'file name' },
{ id: 'license', name: 'License', placeholder: 'specify license' },
{
id: 'caption',
name: 'Caption',
placeholder: 'describe what the image is about',
},
{
id: 'public',
name: 'Public',
render({ value, onChange, required, form }, h) {
return h('input', {
type: 'checkbox',
required,
form,
onChange: (ev) => onChange(ev.target.checked ? 'on' : ''),
defaultChecked: value === 'on',
});
},
},
],
});
```
</details>
<details>
<summary>Example: dynamic meta fields based on file type with a `Function`</summary>
```js
uppy.use(Dashboard, {
trigger: '#pick-files',
metaFields: (file) => {
const fields = [{ id: 'name', name: 'File name' }];
if (file.type.startsWith('image/')) {
fields.push({ id: 'location', name: 'Photo Location' });
fields.push({ id: 'alt', name: 'Alt text' });
fields.push({
id: 'public',
name: 'Public',
render: ({ value, onChange, required, form }, h) => {
return h('input', {
type: 'checkbox',
onChange: (ev) => onChange(ev.target.checked ? 'on' : ''),
defaultChecked: value === 'on',
required,
form,
});
},
});
}
return fields;
},
});
```
</details>
#### `closeModalOnClickOutside`
Set to true to automatically close the modal when the user clicks outside of it
(`boolean`, default: `false`).
#### `closeAfterFinish`
Set to true to automatically close the modal when all current uploads are
complete (`boolean`, default: `false`).
With this option, the modal is only automatically closed when uploads are
complete _and successful_. If some uploads failed, the modal stays open so the
user can retry failed uploads or cancel the current batch and upload an entirely
different set of files instead.
:::info
You can use this together with the
[`allowMultipleUploads: false`](/docs/uppy/#allowmultipleuploads) option in Uppy
Core to create a smooth experience when uploading a single (batch of) file(s).
This is recommended. With several upload batches, the auto-closing behavior can
be quite confusing for users.
:::
#### `disablePageScrollWhenModalOpen`
Disable page scroll when the modal is open (`boolean`, default: `true`).
Page scrolling is disabled by default when the Dashboard modal is open, so when
you scroll a list of files in Uppy, the website in the background stays still.
Set to false to override this behaviour and leave page scrolling intact.
#### `animateOpenClose`
Add animations when the modal dialog is opened or closed, for a more satisfying
user experience (`boolean`, default: `true`).
#### `fileManagerSelectionType`
Configure the type of selections allowed when browsing your file system via the
file manager selection window (`string`, default: `'files'`).
May be either `'files'`, `'folders'`, or `'both'`. Selecting entire folders for
upload may not be supported on all
[browsers](https://caniuse.com/#feat=input-file-directory).
#### `proudlyDisplayPoweredByUppy`
Show the Uppy logo with a link (`boolean`, default: `true`).
Uppy is provided to the world for free by the team behind
[Transloadit](https://transloadit.com). In return, we ask that you consider
keeping a tiny Uppy logo at the bottom of the Dashboard, so that more people can
discover and use Uppy.
#### `disableStatusBar`
Disable the status bar completely (`boolean`, default: `false`).
Dashboard ships with the `StatusBar` plugin that shows upload progress and
pause/resume/cancel buttons. If you want, you can disable the StatusBar to
provide your own custom solution.
#### `disableInformer`
Disable informer (shows notifications in the form of toasts) completely
(`boolean`, default: `false`).
Dashboard ships with the `Informer` plugin that notifies when the browser is
offline, or when its time to say cheese if `Webcam` is taking a picture. If you
want, you can disable the Informer and/or provide your own custom solution.
#### `disableThumbnailGenerator`
Disable the thumbnail generator completely (`boolean`, default: `false`).
Dashboard ships with the `ThumbnailGenerator` plugin that adds small resized
image thumbnails to images, for preview purposes only. If you want, you can
disable the `ThumbnailGenerator` and/or provide your own custom solution.
#### `locale`
```js
module.exports = {
strings: {
// When `inline: false`, used as the screen reader label for the button that closes the modal.
closeModal: 'Close Modal',
// Used as the screen reader label for the plus (+) button that shows the “Add more files” screen
addMoreFiles: 'Add more files',
addingMoreFiles: 'Adding more files',
// Used as the header for import panels, e.g., “Import from Google Drive”.
importFrom: 'Import from %{name}',
// When `inline: false`, used as the screen reader label for the dashboard modal.
dashboardWindowTitle: 'Uppy Dashboard Window (Press escape to close)',
// When `inline: true`, used as the screen reader label for the dashboard area.
dashboardTitle: 'Uppy Dashboard',
// Shown in the Informer when a link to a file was copied to the clipboard.
copyLinkToClipboardSuccess: 'Link copied to clipboard.',
// Used when a link cannot be copied automatically — the user has to select the text from the
// input element below this string.
copyLinkToClipboardFallback: 'Copy the URL below',
// Used as the hover title and screen reader label for buttons that copy a file link.
copyLink: 'Copy link',
back: 'Back',
// Used as the screen reader label for buttons that remove a file.
removeFile: 'Remove file',
// Used as the screen reader label for buttons that open the metadata editor panel for a file.
editFile: 'Edit file',
// Shown in the panel header for the metadata editor. Rendered as “Editing image.png”.
editing: 'Editing %{file}',
// Used as the screen reader label for the button that saves metadata edits and returns to the
// file list view.
finishEditingFile: 'Finish editing file',
saveChanges: 'Save changes',
// Used as the label for the tab button that opens the system file selection dialog.
myDevice: 'My Device',
dropHint: 'Drop your files here',
// Used as the hover text and screen reader label for file progress indicators when
// they have been fully uploaded.
uploadComplete: 'Upload complete',
uploadPaused: 'Upload paused',
// Used as the hover text and screen reader label for the buttons to resume paused uploads.
resumeUpload: 'Resume upload',
// Used as the hover text and screen reader label for the buttons to pause uploads.
pauseUpload: 'Pause upload',
// Used as the hover text and screen reader label for the buttons to retry failed uploads.
retryUpload: 'Retry upload',
// Used as the hover text and screen reader label for the buttons to cancel uploads.
cancelUpload: 'Cancel upload',
// Used in a title, how many files are currently selected
xFilesSelected: {
0: '%{smart_count} file selected',
1: '%{smart_count} files selected',
},
uploadingXFiles: {
0: 'Uploading %{smart_count} file',
1: 'Uploading %{smart_count} files',
},
processingXFiles: {
0: 'Processing %{smart_count} file',
1: 'Processing %{smart_count} files',
},
// The "powered by Uppy" link at the bottom of the Dashboard.
poweredBy: 'Powered by %{uppy}',
addMore: 'Add more',
editFileWithFilename: 'Edit file %{file}',
save: 'Save',
cancel: 'Cancel',
dropPasteFiles: 'Drop files here or %{browseFiles}',
dropPasteFolders: 'Drop files here or %{browseFolders}',
dropPasteBoth: 'Drop files here, %{browseFiles} or %{browseFolders}',
dropPasteImportFiles: 'Drop files here, %{browseFiles} or import from:',
dropPasteImportFolders: 'Drop files here, %{browseFolders} or import from:',
dropPasteImportBoth:
'Drop files here, %{browseFiles}, %{browseFolders} or import from:',
importFiles: 'Import files from:',
browseFiles: 'browse files',
browseFolders: 'browse folders',
recoveredXFiles: {
0: 'We could not fully recover 1 file. Please re-select it and resume the upload.',
1: 'We could not fully recover %{smart_count} files. Please re-select them and resume the upload.',
},
recoveredAllFiles: 'We restored all files. You can now resume the upload.',
sessionRestored: 'Session restored',
reSelect: 'Re-select',
missingRequiredMetaFields: {
0: 'Missing required meta field: %{fields}.',
1: 'Missing required meta fields: %{fields}.',
},
},
};
```
#### `theme`
Light or dark theme for the Dashboard (`string`, default: `'light'`).
Uppy Dashboard supports “Dark Mode”. You can try it live on
[the Dashboard example page](https://uppy.io/examples/).
It supports the following values:
- `light` — the default
- `dark`
- `auto` — will respect the users system settings and switch automatically
#### `autoOpen`
Automatically open file editor for the file user just dropped/selected.
If one file is added, editor opens for that file; if 10 files are added, editor
opens only for the first file.
This option supports the following values:
- `null` - the default
- `"metaEditor"` - open the meta fields editor if
[meta fields](/docs/dashboard/#metafields) are enabled.
- `"imageEditor"` - open [`@uppy/image-editor`](/docs/image-editor) if the
plugin is enabled.
#### `disabled`
Enabling this option makes the Dashboard grayed-out and non-interactive
(`boolean`, default: `false`).
Users wont be able to click on buttons or drop files. Useful when you need to
conditionally enable/disable file uploading or manipulation, based on a
condition in your app. Can be set on init or via API:
```js
const dashboard = uppy.getPlugin('Dashboard');
dashboard.setOptions({ disabled: true });
userNameInput.addEventListener('change', () => {
dashboard.setOptions({ disabled: false });
});
```
#### `disableLocalFiles`
Disable local files (`boolean`, default: `false`).
Enabling this option will disable drag & drop, hide the “browse” and “My Device”
button, allowing only uploads from plugins, such as Webcam, Screen Capture,
Google Drive, Instagram.
#### `onDragOver(event)`
Callback for the [`ondragover`][ondragover] event handler.
#### `onDrop(event)`
Callback for the [`ondrop`][ondrop] event handler.
#### `onDragLeave(event)`
Callback for the [`ondragleave`][ondragleave] event handler.
### Methods
:::info
Dashboard also has the methods described in
[`UIPlugin`](/docs/uppy#new-uipluginuppy-options) and
[`BasePlugin`](/docs/uppy#new-basepluginuppy-options).
:::
#### `openModal()`
Shows the Dashboard modal. Use it like this:
`uppy.getPlugin('Dashboard').openModal()`
#### `closeModal()`
Hides the Dashboard modal. Use it like this:
`uppy.getPlugin('Dashboard').closeModal()`
#### `isModalOpen()`
Returns `true` if the Dashboard modal is open, `false` otherwise.
```js
const dashboard = uppy.getPlugin('Dashboard');
if (dashboard.isModalOpen()) {
dashboard.closeModal();
}
```
### Events
:::info
You can use [`on`](/docs/uppy#onevent-action) and
[`once`](/docs/uppy#onceevent-action) to listen to these events.
:::
#### `dashboard:modal-open`
Fired when the Dashboard modal is open.
```js
uppy.on('dashboard:modal-open', () => {
console.log('Modal is open');
});
```
#### `dashboard:modal-closed`
Fired when the Dashboard modal is closed.
#### `dashboard:file-edit-start`
**Parameters:**
- `file` — The [File Object](https://uppy.io/docs/uppy/#File-Objects)
representing the file that was opened for editing.
Fired when the user clicks “edit” icon next to a file in the Dashboard. The
FileCard panel is then open with file metadata available for editing.
#### `dashboard:file-edit-complete`
**Parameters:**
- `file` — The [File Object](https://uppy.io/docs/uppy/#File-Objects)
representing the file that was edited.
Fired when the user finished editing the file metadata.
## Integrations
These are the plugins specifically made for the Dashboard. This is not a list of
all Uppy plugins.
### Sources
- [`@uppy/audio`](/docs/audio) — record audio.
- [`@uppy/box`](/docs/box) — import files from
[Box](https://www.box.com/en-nl/home).
- [`@uppy/dropbox`](/docs/dropbox) — import from [Dropbox](https://dropbox.com).
- [`@uppy/facebook`](/docs/facebook) — import from
[Facebook](https://facebook.com).
- [`@uppy/google-drive`](/docs/google-drive) — import from
[Google Drive](https://drive.google.com).
- [`@uppy/instagram`](/docs/instagram) — import from
[Instagram](https://instagram.com).
- [`@uppy/onedrive`](/docs/onedrive) — import from
[OneDrive](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage).
- [`@uppy/screen-capture`](/docs/screen-capture) — Record your screen, including
(optionally) your microphone.
- [`@uppy/unsplash`](/docs/unsplash) — import files from
[Unsplash](https://unsplash.com/)
- [`@uppy/url`](/docs/url) — import files from any URL.
- [`@uppy/webcam`](/docs/webcam) — Record or make a picture with your webcam.
- [`@uppy/zoom`](/docs/zoom) — import files from [Zoom](https://zoom.us).
### UI
- [`@uppy/image-editor`](/docs/image-editor) — allows users to crop, rotate,
zoom and flip images that are added to Uppy.
- [`@uppy/informer`](/docs/informer) — show notifications.
- [`@uppy/status-bar`](/docs/status-bar) — advanced upload progress status bar.
- [`@uppy/thumbnail-generator`](/docs/thumbnail-generator) — generate preview
thumbnails for images to be uploaded.
### Frameworks
- [`@uppy/angular`](/docs/angular) — Dashboard component for
[Angular](https://angular.io/).
- [`@uppy/react`](/docs/react) — Dashboard component for
[React](https://reactjs.org/).
- [`@uppy/svelte`](/docs/svelte) — Dashboard component for
[Svelte](https://svelte.dev/).
- [`@uppy/vue`](/docs/vue) — Dashboard component for [Vue](https://vuejs.org/).
[ondragover]:
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondragover
[ondragleave]:
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondragleave
[ondrop]:
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondrop

View file

@ -0,0 +1,149 @@
---
sidebar_position: 2
slug: /drag-drop
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Drag & Drop
The `@uppy/drag-drop` plugin renders a drag and drop area for file selection.
:::tip
[Try out the live example](/examples) or take it for a spin in
[CodeSandbox](https://codesandbox.io/s/uppy-drag-drop-gyewzx?file=/src/index.js).
:::
## When should I use this?
It can be useful when you only want the local device as a file source, dont
need file previews and a UI for metadata editing, or the
[Dashboard](/docs/dashboard/) is too much. But it can be too minimal too. By
default it doesnt show that a file has been added nor is there a progress bar.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/core @uppy/drag-drop
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/core @uppy/drag-drop
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, DragDrop } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(DragDrop, { target: '#uppy' })
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
```js showLineNumbers
import Uppy from '@uppy/core';
import DragDrop from '@uppy/drag-drop';
import '@uppy/core/dist/style.min.css';
import '@uppy/drag-drop/dist/style.min.css';
new Uppy().use(DragDrop, { target: '#drag-drop' });
```
:::info
Certain [restrictions](/docs/uppy#restrictions) set in Uppys options, namely
`maxNumberOfFiles` and `allowedFileTypes`, affect the system file picker dialog.
If `maxNumberOfFiles: 1`, users will only be able to select one file, and
`allowedFileTypes: ['video/*', '.gif']` means only videos or gifs (files with
`.gif` extension) will be selectable.
:::
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, Default: `'DragDrop'`).
Use this if you need to add several DragDrop instances.
#### `target`
DOM element, CSS selector, or plugin to place the drag and drop area into
(`string` or `Element`, default: `null`).
#### `width`
Drag and drop area width (`string`, default: `'100%'`).
Set in inline CSS, so feel free to use percentage, pixels or other values that
you like.
#### `height`
Drag and drop area height (`string`, default: `'100%'`).
Set in inline CSS, so feel free to use percentage, pixels or other values that
you like.
#### `note`
Optionally, specify a string of text that explains something about the upload
for the user (`string`, default: `null`).
This is a place to explain any `restrictions` that are put in place. For
example: `'Images and video only, 23 files, up to 1 MB'`.
#### `locale`
```js
export default {
strings: {
// Text to show on the droppable area.
// `%{browse}` is replaced with a link that opens the system file selection dialog.
dropHereOr: 'Drop here or %{browse}',
// Used as the label for the link that opens the system file selection dialog.
browse: 'browse',
},
};
```
#### `onDragOver(event)`
Callback for the [`ondragover`][ondragover] event handler.
#### `onDragLeave(event)`
Callback for the [`ondragleave`][ondragleave] event handler.
#### `onDrop(event)`
Callback for the [`ondrop`][ondrop] event handler.
[ondragover]:
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondragover
[ondragleave]:
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondragleave
[ondrop]:
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondrop

View file

@ -0,0 +1,5 @@
{
"label": "Elements",
"position": 3,
"collapsed": false
}

View file

@ -0,0 +1,113 @@
---
sidebar_position: 2
slug: /drop-target
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Drop target
The `@uppy/drop-target` plugin lets your users drag-and-drop files on any
element on the page, for example the whole page, `document.body`.
Can be used together with Uppy Dashboard or Drag & Drop plugins, or your custom
solution targeting any DOM element.
:::tip
[Try out the live example](/examples) or take it for a spin in
[CodeSandbox](https://codesandbox.io/s/uppy-drag-drop-gyewzx?file=/src/index.js).
:::
## When should I use this?
When you want to allow users to drag and drop files in your own UI, rather than
in the [`Dashboard`](/docs/dashboard) UI, or catch dropped files from anywhere
on the page.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/drop-target
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/drop-target
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { DropTarget } from "{{UPPY_JS_URL}}"
const DropTarget = new Uppy().use(DropTarget)
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
This module has one default export: the `DropTarget` plugin class.
```js {8-10} showLineNumbers
import Uppy from '@uppy/core';
import DropTarget from '@uppy/drop-target';
import '@uppy/core/dist/style.css';
import '@uppy/drop-target/dist/style.css';
const uppy = new Uppy();
uppy.use(DropTarget, {
target: document.body,
});
```
## API
### Options
#### `onDragLeave`
Event listener for the [`dragleave` event][].
```js {3-5} showLineNumbers
uppy.use(DropTarget, {
target: document.body,
onDragLeave: (event) => {
event.stopPropagation();
},
});
```
#### `onDragOver`
Event listener for the [`dragover` event][].
#### `onDrop`
Event listener for the [`drop` event][].
#### `target`
DOM element, CSS selector, or plugin to place the drag and drop area into
(`string`, `Element`, `Function`, or `UIPlugin`, default: `null`).
[`dragover` event]:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragover_event
[`dragleave` event]:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragleave_event
[`drop` event]:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/drop_event

View file

@ -0,0 +1,179 @@
---
sidebar_position: 1
slug: /image-editor
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Image editor
Image editor. Designed to be used with the Dashboard UI.
<div style={{ maxWidth: 500 }}>
![Screenshot of the Image Editor plugin UI in Dashboard](https://user-images.githubusercontent.com/1199054/87208710-654db400-c307-11ea-9471-6e3c6582d2a5.png)
</div>
## When should I use this?
When you want to allow users to crop, rotate, zoom and flip images that are
added to Uppy.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/core @uppy/dashboard @uppy/image-editor
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/core @uppy/dashboard @uppy/image-editor
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Dashboard, ImageEditor } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(Dashboard, { target: '#uppy', inline: true })
uppy.use(ImageEditor, { target: Uppy.Dashboard })
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
```js {3,7,11} showLineNumbers
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import ImageEditor from '@uppy/image-editor';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
import '@uppy/image-editor/dist/style.min.css';
new Uppy()
.use(Dashboard, { inline: true, target: '#dashboard' })
.use(ImageEditor, { target: Dashboard });
```
## API
### Options
:::info
If you automatically want to open the image editor when an image is added, see
the [`autoOpen`](/docs/dashboard#autoopen) Dashboard option.
:::
#### `id`
A unique identifier for this plugin (`string`, default: `'ImageEditor'`).
#### `quality`
Quality Of the resulting blob that will be saved in Uppy after editing/cropping
(`number`, default: `0.8`).
#### `cropperOptions`
Image Editor is using the excellent
[Cropper.js](https://fengyuanchen.github.io/cropperjs/). `cropperOptions` will
be directly passed to `Cropper` and thus can expect the same values as
documented in their
[README](https://github.com/fengyuanchen/cropperjs/blob/HEAD/README.md#options),
with the addition of `croppedCanvasOptions`, which will be passed to
[`getCroppedCanvas`](https://github.com/fengyuanchen/cropperjs/blob/HEAD/README.md#getcroppedcanvasoptions).
#### `actions`
Show action buttons (`Object` or `boolean`).
If you youd like to hide all actions, pass `false` to it. By default all the
actions are visible. Or enable/disable them individually:
```js
{
revert: true,
rotate: true,
granularRotate: true,
flip: true,
zoomIn: true,
zoomOut: true,
cropSquare: true,
cropWidescreen: true,
cropWidescreenVertical: true,
}
```
#### `locale: {}`
```js
export default {
strings: {
revert: 'Revert',
rotate: 'Rotate',
zoomIn: 'Zoom in',
zoomOut: 'Zoom out',
flipHorizontal: 'Flip horizontal',
aspectRatioSquare: 'Crop square',
aspectRatioLandscape: 'Crop landscape (16:9)',
aspectRatioPortrait: 'Crop portrait (9:16)',
},
};
```
### Events
:::info
You can use [`on`](/docs/uppy#onevent-action) and
[`once`](/docs/uppy#onceevent-action) to listen to these events.
:::
#### `file-editor:start`
Emitted when `selectFile(file)` is called.
```js
uppy.on('file-editor:start', (file) => {
console.log(file);
});
```
#### `file-editor:complete`
Emitted after `save(blob)` is called.
```js
uppy.on('file-editor:complete', (updatedFile) => {
console.log(updatedFile);
});
```
#### `file-editor:cancel`
Emitted when `uninstall` is called or when the current image editing changes are
discarded.
```js
uppy.on('file-editor:cancel', (file) => {
console.log(file);
});
```

View file

@ -0,0 +1,94 @@
---
sidebar_position: 3
slug: /informer
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Informer
The `@uppy/informer` plugin is a pop-up bar for showing notifications for the
[Dashboard](/docs/dashboard). When plugins have some exciting news (or errors)
to share, they can with Informer
## When should I use it?
When you use the [Dashboard](/docs/dashboard) its already included by default.
This plugin is published separately but made specifically for the Dashboard. You
can technically use it without it, but its not officially supported.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/informer
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/informer
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, Informer } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(Informer, { target: '#informer' })
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
```js
import Uppy from '@uppy/core';
import Informer from '@uppy/informer';
// The `@uppy/informer` plugin includes some basic styles.
// You can also choose not to use it and provide your own styles instead.
import '@uppy/core/dist/style.min.css';
import '@uppy/informer/dist/style.min.css';
new Uppy().use(Informer, { target: '#informer' });
```
Informer gets its data from `uppy.state.info`, which is updated by various
plugins via [`uppy.info`](/docs/uppy#infomessage-type-duration) method.
In the [compressor](/docs/compressor) plugin we use it like this for instance:
```js
const size = prettierBytes(totalCompressedSize);
this.uppy.info(this.i18n('compressedX', { size }), 'info');
```
When calling `uppy.info`, [Uppy](/docs/uppy) emits
[`info-visible`](/docs/uppy#info-visible) and will emit
[`info-hidden`](/docs/uppy#info-hidden) after the timeout.
## API
### Options
### `id`
A unique identifier for this plugin (`string`, default: `'Informer'`).
Use this if you need several `Informer` instances.
### `target`
DOM element, CSS selector, or plugin to mount the Informer into (`string` or
`Element`, default: `null`).

View file

@ -0,0 +1,91 @@
---
sidebar_position: 5
slug: /progress-bar
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Progress bar
`@uppy/progress-bar` is a minimalist plugin that shows the current upload
progress in a thin bar element, like the ones used by YouTube and GitHub when
navigating between pages.
## When should I use it?
When you need a minimalistec progress indicator and youre
[building your own UI](/docs/guides/building-your-own-ui-with-uppy). For most
cases, [Dashboard](/docs/dashboard) or [Drag & Drop](/docs/drag-drop) (with
[Status Bar](/docs/status-bar)) is more likely what you need.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/progress-bar
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/progress-bar
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, ProgressBar } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(ProgressBar, { target: '#progress-bar' })
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
```js
import Uppy from '@uppy/core';
import ProgressBar from '@uppy/progress-bar';
import '@uppy/core/dist/style.min.css';
import '@uppy/progress-bar/dist/style.min.css';
new Uppy().use(ProgressBar, { target: '#progress-bar' });
```
## API
### Options
#### `id`
A unique identifier for this Progress Bar (`string`, default: `'ProgressBar'`).
Use this if you need to add several ProgressBar instances.
#### `target`
DOM element, CSS selector, or plugin to mount the Progress Bar into (`Element`,
`string`, default: `null`).
#### `fixed`
Show the progress bar at the top of the page with `position: fixed` (`boolean`,
default: `false`).
When set to false, show the progress bar inline wherever its mounted.
#### `hideAfterFinish`
Hides the progress bar after the upload has finished (`boolean`, default:
`true`).

View file

@ -0,0 +1,201 @@
---
sidebar_position: 4
slug: /status-bar
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Status bar
The `@uppy/status-bar` plugin shows upload progress and speed, estimated time,
pre- and post-processing information, and allows users to control
(pause/resume/cancel) the upload.
:::tip
Try it out together with [`@uppy/drag-drop`](/docs/drag-drop) in
[CodeSandbox](https://codesandbox.io/s/uppy-drag-drop-gyewzx?file=/src/index.js)
:::
## When should I use it?
When you use the [Dashboard](/docs/dashboard) its already included by default.
This plugin is published separately but made specifically for the Dashboard. You
can still use it without it but it may need some (CSS) tweaking for your use
case.
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/status-bar
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/status-bar
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, StatusBar } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(StatusBar, { target: '#status-bar' })
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
```js showLineNumbers
import Uppy from '@uppy/core';
import StatusBar from '@uppy/status-bar';
import '@uppy/core/dist/style.min.css';
import '@uppy/status-bar/dist/style.min.css';
new Uppy().use(StatusBar, { target: '#status-bar' });
```
## API
### Options
#### `id`
A unique identifier for this Status Bar (`string`, default: `'StatusBar'`).
Use this if you need to add several StatusBar instances.
#### `target`
DOM element, CSS selector, or plugin to mount the Status Bar into (`Element`,
`string`, `UIPlugin`, default: `'body'`).
#### `hideAfterFinish`
Hide the Status Bar after the upload is complete (`boolean`, default: `true`).
#### `showProgressDetails`
Display remaining upload size and estimated time (`boolean`, default: `false`)
:::note
`false`: Uploading: 45%
`true`: Uploading: 45%・43 MB of 101 MB・8s left
:::
#### `hideUploadButton`
Hide the upload button (`boolean`, default: `false`).
Use this if you are providing a custom upload button somewhere, and using the
`uppy.upload()` API.
#### `hideRetryButton`
Hide the retry button (`boolean`, default: `false`).
Use this if you are providing a custom retry button somewhere, and using the
`uppy.retryAll()` or `uppy.retryUpload(fileID)` API.
#### `hidePauseResumeButton`
Hide pause/resume buttons (for resumable uploads, via [tus](http://tus.io), for
example) (`boolean`, default: `false`).
Use this if you are providing custom cancel or pause/resume buttons somewhere,
and using the `uppy.pauseResume(fileID)` or `uppy.removeFile(fileID)` API.
#### `hideCancelButton`
Hide the cancel button (`boolean`, default: `false`).
Use this if you are providing a custom retry button somewhere, and using the
`uppy.cancelAll()` API.
#### `doneButtonHandler`
Status Bar will render a “Done” button in place of pause/resume/cancel buttons,
once the upload/encoding is done (`Function`, default: `null`).
The behaviour of this “Done” button is defined by the handler function — can be
used to close file picker modals or clear the upload state. This is what the
Dashboard plugin, which uses Status Bar internally, sets:
```js
const doneButtonHandler = () => {
this.uppy.reset();
this.requestCloseModal();
};
```
#### `locale`
```js
export default {
strings: {
// Shown in the status bar while files are being uploaded.
uploading: 'Uploading',
// Shown in the status bar once all files have been uploaded.
complete: 'Complete',
// Shown in the status bar if an upload failed.
uploadFailed: 'Upload failed',
// Shown in the status bar while the upload is paused.
paused: 'Paused',
// Used as the label for the button that retries an upload.
retry: 'Retry',
// Used as the label for the button that cancels an upload.
cancel: 'Cancel',
// Used as the label for the button that pauses an upload.
pause: 'Pause',
// Used as the label for the button that resumes an upload.
resume: 'Resume',
// Used as the label for the button that resets the upload state after an upload
done: 'Done',
// When `showProgressDetails` is set, shows the number of files that have been fully uploaded so far.
filesUploadedOfTotal: {
0: '%{complete} of %{smart_count} file uploaded',
1: '%{complete} of %{smart_count} files uploaded',
},
// When `showProgressDetails` is set, shows the amount of bytes that have been uploaded so far.
dataUploadedOfTotal: '%{complete} of %{total}',
// When `showProgressDetails` is set, shows an estimation of how long the upload will take to complete.
xTimeLeft: '%{time} left',
// Used as the label for the button that starts an upload.
uploadXFiles: {
0: 'Upload %{smart_count} file',
1: 'Upload %{smart_count} files',
},
// Used as the label for the button that starts an upload, if another upload has been started in the past
// and new files were added later.
uploadXNewFiles: {
0: 'Upload +%{smart_count} file',
1: 'Upload +%{smart_count} files',
},
upload: 'Upload',
retryUpload: 'Retry upload',
xMoreFilesAdded: {
0: '%{smart_count} more file added',
1: '%{smart_count} more files added',
},
showErrorDetails: 'Show error details',
},
};
```

View file

@ -0,0 +1,168 @@
---
sidebar_position: 2
slug: /thumbnail-generator
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import UppyCdnExample from '/src/components/UppyCdnExample';
# Thumbnail generator
`@uppy/thumbnail-generator` generates proportional thumbnails (file previews)
for images that are added to Uppy.
## When should I use this?
This plugin is included by default with the [Dashboard](/docs/dashboard) plugin,
and can also be useful to display image previews in a custom UI.
:::note
Thumbnails are only generated for _local_ files. Remote files through
[Companion](/docs/companion) generally wont have thumbnails because they are
downloaded on the server. Some providers, such as Google Drive, have baked in
thumbnails into their API responses.
:::
## Install
<Tabs>
<TabItem value="npm" label="NPM" default>
```shell
npm install @uppy/thumbnail-generator
```
</TabItem>
<TabItem value="yarn" label="Yarn">
```shell
yarn add @uppy/thumbnail-generator
```
</TabItem>
<TabItem value="cdn" label="CDN">
<UppyCdnExample>
{`
import { Uppy, ThumbnailGenerator } from "{{UPPY_JS_URL}}"
const uppy = new Uppy()
uppy.use(ThumbnailGenerator)
`}
</UppyCdnExample>
</TabItem>
</Tabs>
## Use
If you use the [Dashboard](/docs/dashboard) then its already installed. If you
want to use it programmatically for your own UI:
```js showLineNumbers
import Uppy from '@uppy/core';
import ThumbnailGenerator from '@uppy/thumbnail-generator';
const uppy = new Uppy();
uppy.use(ThumbnailGenerator);
uppy.on('thumbnail:generated', (file, preview) => doSomething(file, preview));
```
## API
### Options
#### `id`
A unique identifier for this plugin (`string`, default: `'ThumbnailGenerator'`).
#### `locale`
```js
export default {
strings: {
generatingThumbnails: 'Generating thumbnails...',
},
};
```
#### `thumbnailWidth`
Width of the resulting thumbnail (`number`, default: `200`).
Thumbnails are always proportional and not cropped. If width is provided, height
is calculated automatically to match ratio. If both width and height are given,
only width is taken into account.
#### `thumbnailHeight`
Height of the resulting thumbnail (`number`, default: `200`).
Thumbnails are always proportional and not cropped. If height is provided, width
is calculated automatically to match ratio. If both width and height are given,
only width is taken into account.
:::note
Produce a 300px height thumbnail with calculated width to match ratio:
```js
uppy.use(ThumbnailGenerator, { thumbnailHeight: 300 });
```
Produce a 300px width thumbnail with calculated height to match ratio (and
ignore the given height):
```js
uppy.use(ThumbnailGenerator, { thumbnailWidth: 300, thumbnailHeight: 300 });
```
See issue [#979](https://github.com/transloadit/uppy/issues/979) and
[#1096](https://github.com/transloadit/uppy/pull/1096) for details on this
feature.
:::
#### `thumbnailType`
MIME type of the resulting thumbnail (`string`, default: `'image/jpeg'`).
This is useful if you want to support transparency in your thumbnails by
switching to `image/png`.
#### `waitForThumbnailsBeforeUpload`
Whether to wait for all thumbnails to be ready before starting the upload
(`boolean`, default: `false`).
If set to `true`, Thumbnail Generator will invoke Uppys internal processing
stage and wait for `thumbnail:all-generated` event, before proceeding to the
uploading stage. This is useful because Thumbnail Generator also adds EXIF data
to images, and if we wait until its done processing, this data will be
available on the server after the upload.
### Events
:::info
You can use [`on`](/docs/uppy#onevent-action) and
[`once`](/docs/uppy#onceevent-action) to listen to these events.
:::
#### `thumbnail:generated`
Emitted with `file` and `preview` local url as arguments:
```js
uppy.on('thumbnail:generated', (file, preview) => {
const img = document.createElement('img');
img.src = preview;
img.width = 100;
document.body.appendChild(img);
});
```