File & Image Upload Widget
(With Integrated Cloud Storage)
100% Serverless File Upload Widget
Powered by Bytescale
DMCA Compliant โข GDPR Compliant โข 99.9% Uptime SLA
Supports: Rate Limiting, Volume Limiting, File Size & Type Limiting, JWT Auth, and more...
Installation
Install via NPM:
npm install uploader
Or via YARN:
yarn add uploader
Or via a <script>
tag:
<script src="https://js.bytescale.com/uploader/v3"></script>
Usage
Initialize
Initialize once at the start of your application:
const { Uploader } = require("uploader");
const uploader = Uploader({
apiKey: "free"
});
uploader.open({ multi: true }).then(files => {
if (files.length === 0) {
console.log('No files selected.')
} else {
console.log('Files uploaded:');
console.log(files.map(f => f.fileUrl));
}
}).catch(err => {
console.error(err);
});
Get the Result
.open()
returns Promise<Array<UploaderResult>>
:
{
fileUrl: "https://upcdn.io/FW25...",
filePath: "/uploads/example.jpg",
editedFile: undefined,
originalFile: {
fileUrl: "https://upcdn.io/FW25...",
filePath: "/uploads/example.jpg",
accountId: "FW251aX",
originalFileName: "example.jpg",
file: { ... },
size: 12345,
lastModified: 1663410542397,
mime: "image/jpeg",
metadata: {
...
},
tags: [
"tag1",
"tag2",
...
]
}
}
๐ More Examples
Creating an Image Uploader โ Try on CodePen:
Uploader contains a built-in image cropper:
The cropper appears by default, but can be disabled with crop: false
(see examples below):
uploader
.open({
multi: false,
mimeTypes: ["image/*"],
editor: {
images: {
crop: true,
cropShape: "circ",
cropRatio: 1 / 1
}
}
})
.then(files => alert(JSON.stringify(files)));
How does image cropping work?
The image cropper uses server-side image cropping, and works like so:
- First, the original image is uploaded, with no cropping applied.
- If the user-provided crop geometry matches the original image geometry, then no further action is taken.
- The
filePath
in the result will reference the original image.
- Else a 2nd file is uploaded containing JSON that describes the crop geometry and includes a reference to the original image's
filePath
.
- The
filePath
in the result will reference the JSON file.
- When a JSON file is requested via the Image Processing API, then the crop described by the JSON file will be applied first, followed by any additional transformations you have specified via the URL.
Creating a "Single File" Upload Button โ Try on CodePen:
uploader.open().then(files => alert(JSON.stringify(files)));
Creating a "Multi File" Upload Button โ Try on CodePen:
uploader.open({ multi: true }).then(files => alert(JSON.stringify(files)));
You can use Uploader as a dropzone โ rather than a modal โ by specifying layout: "inline"
and a container:
uploader.open({
multi: true,
layout: "inline",
container: "#example_div_id",
onUpdate: (files) => console.log(files)
})
Note:
- You must set
position: relative
, width
and height
on the container div
. - The
Finish
button is hidden by default in this mode (override with "showFinishButton": true
).
โ๏ธ Configuration
All configuration is optional.
uploader
.open({
container: "body",
layout: "modal",
locale: myCustomLocale,
maxFileCount: 5,
maxFileSizeBytes: 1024 ** 2,
mimeTypes: ["image/*"],
multi: false,
onInit: ({ // Exposes lifecycle methods for the component.
close, // Closes the widget when called.
reset, // Resets the widget when called.
updateConfig // Updates the widget's config by passing a new config
}) => {}, // object to the method's first parameter.
onUpdate: files => {}, // Called each time the list of uploaded files change.
onPreUpload: async file => ({
errorMessage: "Uh oh!", // Displays this error message to the user (if set).
transformedFile: file // Uploads 'transformedFile' instead of 'file' (if set).
}),
showFinishButton: true, // Show/hide the "finish" button in the widget.
showRemoveButton: true, // Show/hide the "remove" button next to each file.
styles: {
colors: {
primary: "#377dff", // Primary buttons & links
active: "#528fff", // Primary buttons & links (hover). Inferred if undefined.
error: "#d23f4d", // Error messages
shade100: "#333", // Standard text
shade200: "#7a7a7a", // Secondary button text
shade300: "#999", // Secondary button text (hover)
shade400: "#a5a6a8", // Welcome text
shade500: "#d3d3d3", // Modal close button
shade600: "#dddddd", // Border
shade700: "#f0f0f0", // Progress indicator background
shade800: "#f8f8f8", // File item background
shade900: "#fff" // Various (draggable crop buttons, etc.)
},
fontFamilies: {
base: "arial, sans-serif" // Base font family (comma-delimited).
},
fontSizes: {
base: 16 // Base font size (px).
}
},
path: { // Optional: a string (full file path) or object like so:
fileName: "Example.jpg", // Supports path variables (e.g. {ORIGINAL_FILE_EXT}).
folderPath: "/uploads" // Please refer to docs for all path variables.
},
metadata: {
hello: "world" // Arbitrary JSON metadata (saved against the file).
},
tags: ["profile_picture"], // Requires a Bytescale account.
editor: {
images: {
preview: true, // True by default if cropping is enabled. Previews PDFs and videos too.
crop: true, // True by default.
cropFilePath: image => { // Choose the file path used for JSON image crop files.
const {filePath} = image // In: https://www.bytescale.com/docs/upload-api/types/FileDetails
return `${filePath}.crop` // Out: https://www.bytescale.com/docs/upload-api/types/FilePathDefinition
},
cropRatio: 4 / 3, // Width / Height. Undefined enables freeform (default).
cropShape: "rect" // "rect" (default) or "circ".
}
},
})
.then(files => alert(files))
๐ณ๏ธ Localization
Default is EN_US:
const myCustomLocale = {
"error!": "Error!",
"done": "Done",
"addAnotherFile": "Add another file...",
"addAnotherImage": "Add another image...",
"cancel": "cancel",
"cancelInPreviewWindow": "Cancel",
"cancelled!": "cancelled",
"continue": "Continue",
"customValidationFailed": "Failed to validate file.",
"crop": "Crop",
"finish": "Finished",
"finishIcon": true,
"image": "Image",
"maxFilesReached": "Maximum number of files:",
"maxImagesReached": "Maximum number of images:",
"maxSize": "File size limit:",
"next": "Next",
"of": "of",
"orDragDropFile": "...or drag and drop a file.",
"orDragDropFiles": "...or drag and drop files.",
"orDragDropImage": "...or drag and drop an image.",
"orDragDropImages": "...or drag and drop images.",
"pleaseWait": "Please wait...",
"removed!": "removed",
"remove": "remove",
"skip": "Skip",
"unsupportedFileType": "File type not supported.",
"uploadFile": "Upload a File",
"uploadFiles": "Upload Files",
"uploadImage": "Upload an Image",
"uploadImages": "Upload Images",
"validatingFile": "Validating file..."
}
๐ API Support
๐ File Management API
Bytescale provides an Upload API, which supports the following:
- File uploading.
- File listing.
- File deleting.
- And more...
Uploading a "Hello World"
text file is as simple as:
curl --data "Hello World" \
-u apikey:free \
-X POST "https://api.bytescale.com/v1/files/basic"
Note: Remember to set -H "Content-Type: mime/type"
when uploading other file types!
Read the Upload API docs ยป
๐ Image Processing API (Resize, Crop, etc.)
Bytescale also provides an Image Processing API, which supports the following:
Read the Image Processing API docs ยป
Original Image
Here's an example using a photo of Chicago:
https://upcdn.io/W142hJk/raw/example/city-landscape.jpg
Processed Image
Using the Image Processing API, you can produce this image:
https://upcdn.io/W142hJk/image/example/city-landscape.jpg
?w=900
&h=600
&fit=crop
&f=webp
&q=80
&blur=4
&text=WATERMARK
&layer-opacity=80
&blend=overlay
&layer-rotate=315
&font-size=100
&padding=10
&font-weight=900
&color=ffffff
&repeat=true
&text=Chicago
&gravity=bottom
&padding-x=50
&padding-bottom=20
&font=/example/fonts/Lobster.ttf
&color=ffe400
Full Documentation
Uploader Documentation ยป
Need a Headless (no UI) File Upload Library?
Try Upload.js ยป
Can I use my own storage?
Yes: Bytescale supports AWS S3, Cloudflare R2, Google Storage, and DigitalOcean Spaces.
To configure a custom storage backend, please see:
https://www.bytescale.com/docs/storage/sources
๐ Create your Bytescale Account
Uploader is the Upload Widget for Bytescale: the best way to serve images, videos, and audio for web apps.
Create a Bytescale account ยป
Building From Source
BUILD.md
License
MIT