Uppy File Uploading

By  on  
Uppy

One of the big tasks I was charged with at my first job was setting up a system by which any customer or potential customer (aka anonymous user) could upload PDF and image files. I had loads of constraints to deal with: browser support, server settings, variance in user tech knowledge, etc. Ultimately we needed to use a Java Applet (!) to get the job done. Gross.

Luckily all of the constraints I had to deal with back then have improved and most of the limitations I faced have been resolved. Today I could use Uppy, an open source, elegant, robust utility for file uploading. It's super customizable and easy for you, the developer, to implement and for your users to use. Let's have a look!

Quick Hits

  • Open source!
  • Very little code required to implement
  • Front-end widget is elegant and easy to use
  • Uploads can happen without page reload
  • State recovery (making uploads survive browser crashes or accidental navigate-aways)
  • Works well on mobile
  • Works with any JavaScript framework
  • Provides a wide array of plugins to enrich the uploading experience
  • Easy to localize strings (supply your own pirate language, Shiver me timbers!)
  • Can upload to your existing Apache server (XHR)
  • or: Can upload directly to S3
  • or: Can upload to a Tus-enabled server (making uploads survive travel- and poor network conditions)
  • Provides a server utility that lets your users fetch from Google Drive, Dropbox, Instagram
  • Brought to you by the people behind Transloadit. They offer encoding features, and hosted versions of the Uppy Server utility and Tus

At a Glance Demo

Have a look at usage of Uppy's widget in action:

The Uppy widget:

  • provides a elegant, well-designed interface
  • features drag and drop file uploading
  • allows pausable and resumable uploading
  • provides a method for renaming uploaded files

Let's have a look at the code to put this together!

Implementing the Uppy File Uploader

The creators of Uppy got implementation right: make the developer implement the least amount of code necessary to have a functional, "drop in place" utility. Start by installing Uppy:

Add the CSS and JavaScript libraries to the page:

<!-- In the header -->
<link href="https://transloadit.edgly.net/releases/uppy/v0.25.2/dist/uppy.min.css" rel="stylesheet">

<!-- Where the drag and drop will be -->
<div id="drag-drop-area"></div>

<!-- Bottom of the page -->
<script src="https://transloadit.edgly.net/releases/uppy/v0.25.2/dist/uppy.min.js"></script>

Then initialize Uppy!

<script>
  var uppy = Uppy.Core({ autoProceed: false })
  uppy.use(Uppy.Dashboard, { target: '#drag-drop-area', inline: true })
  uppy.use(Uppy.XHRUpload, { endpoint: 'https://mywebsite.com/receive-file.php' })
</script>

Boom! You have an awesome file upload utility with little hassle that looks great! Check out the live version on CodePen

If you don't want to run Uppy of a CDN and prefer to build it yourself with Browserify or Webpack, just use npm instead:

npm install uppy --save
<script>
var Uppy = require('uppy/lib/core')
var Dashboard = require('uppy/lib/plugins/Dashboard')
var XHRUpload = require('uppy/lib/plugins/XHRUpload')

const uppy = Uppy({ autoProceed: false })
uppy.use(Dashboard, { target: '#drag-drop-area', inline: true })
uppy.use(XHRUpload, { endpoint: 'https://mywebsite.com/receive-file.php' })
</script>

Uppy also provides you a number of events for file uploads:

uppy.on('file-added', (file) => {
  // Do something
});

uppy.on('upload', (data) => {
  // Do something
})

uppy.on('complete', (result) => {
  // Do something
})

Uppy's API is so easy to use that you can consider it a "drop in" API for incredible JavaScript uploading

Want to use any of the Uppy plugins? It's actually pretty easy -- let's check out implementation of what everyone expects from uploads these days, drag & drop:

const Dashboard = require('uppy/lib/plugins/Dashboard')

uppy.use(Dashboard, { target: '#drag-drop-area', inline: true })

The Dashboard plugin here renders a clean and simple drag and drop area, shows file previews, lets you edit meta data and shows upload progress. It acts as a host for other plugins. When you add the Webcam or Instagram plugins, they appear in the Dashboard as tabs, and your users can then select files from any of those as well.

Now let's add the Webcam plugin:

const Webcam = require('uppy/lib/plugins/Webcam')

uppy.use(Webcam, {
  countdown: false,
  mirror: true,
  facingMode: 'user',
  target: Dashboard // Webcam will be installed to the Dashboard
})

Uppy Server

With the XHRUpload plugin Uppy will upload to your existing Apache/Nginx/Node.js/Ruby/PHP server from local disk or webcam. No Uppy Server required. If however you want to add fetching files from Dropbox and Instagram, you will need to run an Uppy Server in the cloud. Uppy Server is open source as well, so you can host it yourself. The API docs are super detailed!

The advantages of having a helper like Uppy Server in the cloud are clear. If your user is on mobile, and picks a 5GB file from their Dropbox, it won't have to be fetched to their phone, and then uploaded. Instead, the file is moved directly between servers. This saves a lot of bandwidth and battery. This is what Uppy Server facilitates, as well as managing the secrets required to access these files.

Let's look at a demo how you could easily allow fetching from remote providers like Google Drive and Dropbox or a plain accessible URL:

const GoogleDrive = require('uppy/lib/plugins/GoogleDrive')
const Url = require('uppy/lib/plugins/Url')

// remote providers require the uppy server utility. 
// we're using the public demo server in this case:
uppy.use(GoogleDrive, { target: Dashboard, host: 'https://server.uppy.io/' })
uppy.use(Url, { target: Dashboard, host: 'https://server.uppy.io/ })

If you decide you want Uppy Server but not host it, you could also let Transloadit handle that. Transloadit created both Uppy and the Tus standard. It might come in handy that Transloadit also offers integrated virus scan, image crop, transcode, face detect, and more. They will store the results on storage of your choosing. This way you'll always own all content, and you can be confident that what is uploaded, displays optimally on all devices and browsers.

Transloadit

I hadn't heard about Transloadit before but it seems they're a small remote company that's been relentlessly trying to advance the file uploading & processing space, and that the majority of their tech has been released as open source 💗

Transloadit's uploading and processing service delivers an awesome array of functionality:

  • Resize, crop, and watermark images
  • Convert videos to GIFs, and visa versa
  • Transcode video and extract thumbnails
  • Take website screenshots
  • Create waveform images from audio
  • Create slideshow videos from images and audio
  • Chain conversions together to create unique "workflows" in a single declaritive JSON language
  • Stability of 99.99% uptime over 9 years
  • Manipulate media on the fly
  • Integrates well for different media types and different languages and frameworks
  • Trusted by Coursera, The New York Times, Oracle, Cambridge University, and more

As a final demo, let's look at a simple example of how Uppy plays with Transloadit, for when you want to, say, add a "Powered by Uppy" text to images that your users are uploading:

const Uppy = require('uppy/lib/core')
const Dashboard = require('uppy/lib/plugins/Dashboard')
const Transloadit = require('uppy/lib/plugins/Transloadit')

const uppy = Uppy()
  .use(Dashboard, { target: '#drag-drop-area', inline: true })
  .use(Transloadit, {
    waitForEncoding: true,
    params: {
      auth: { key: YOUR_TRANSLOADIT_KEY },
      steps: {
        resize: {
          width: 250,
          height: 250,
          robot: '/image/resize',
          text: [{'text': 'Powered by Uppy', 'font': 'Ubuntu', 'color': '#eeeeee', 'valign': 'bottom', 'align': 'right', 'x_offset': 16, 'y_offset': -10}]
        }
      }
    }
  })

uppy.on('transloadit:result', (stepName, result) => {
  // use transloadit encoding result here.
  console.log('Result here ====>', stepName, result)
  console.log('Cropped image url is here ====>', result.url)
})

Check out an interactive Uppy+Transloadit demo

Managing file uploads, from both the client side and server side perspectives can be a total nightmare; add how difficult drag & drop as well as upload validation can be and having an awesome file uploader seems like a unicorn. Uppy seems like the real deal: configurable, easy to implement, elegant UI, server control, open source, modern, modular, and more -- you can't ask for much else!

Recent Features

  • By
    LightFace:  Facebook Lightbox for MooTools

    One of the web components I've always loved has been Facebook's modal dialog.  This "lightbox" isn't like others:  no dark overlay, no obnoxious animating to size, and it doesn't try to do "too much."  With Facebook's dialog in mind, I've created LightFace:  a Facebook lightbox...

  • By
    How to Create a Twitter Card

    One of my favorite social APIs was the Open Graph API adopted by Facebook.  Adding just a few META tags to each page allowed links to my article to be styled and presented the way I wanted them to, giving me a bit of control...

Incredible Demos

  • By
    Create Your Own Dijit CSS Theme with LESS CSS

    The Dojo Toolkit seems to just get better and better.  One of the new additions in Dojo 1.6 was the use of LESS CSS to create Dijit themes.  The move to using LESS is a brilliant one because it makes creating your own Dijit theme...

  • By
    Six Degrees of Kevin Bacon Using MooTools 1.2

    As you can probably tell, I try to mix some fun in with my MooTools madness but I also try to make my examples as practical as possible. Well...this may not be one of those times. I love movies and useless movie trivia so naturally I'm...

Discussion

  1. Seems very compelling. I’ve been using PLUpload for the last 5+ years and it’s been great. But, it has some timing problems in that it initializes asynchronously, which can lead to bugs that I can’t fix easily. I’ll take a look at Uppy to see how it looks.

  2. Warren Churulich

    Nice article. I appreciate the working demos.
    I’d love to see a working demo with instructions for uploading directly to AWS S3.

  3. How to create those companion endpoint in the same PHP server rather than using Node. Any ideas will be appreciated!

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!