martinklepsch / s3-beam

🚀 direct-to-S3 uploading using ClojureScript
Eclipse Public License 1.0
92 stars 17 forks source link
aws cljs clojurescript digitalocean direct-upload s3 signing-server

s3-beam Dependencies Status

Usage | Changes

s3-beam is a Clojure/Clojurescript library designed to help you upload files from the browser to S3 (CORS upload). s3-beam can also upload files from the browser to DigitalOcean Spaces.

[org.martinklepsch/s3-beam "0.6.0-alpha5"] ;; latest release

Usage

To upload files directly to S3 you need to send special request parameters that are based on your AWS credentials, the file name, mime type, date etc. Since we don't want to store our credentials in the client these parameters need to be generated on the server side. For this reason this library consists of two parts:

  1. A pluggable route that will send back the required parameters for a given file-name & mime-type
  2. A client-side core.async pipeline setup that will retrieve the special parameters for a given File object, upload it to S3 and report back to you

1. Enable CORS on your S3 bucket

Please follow Amazon's official documentation.

For DigitalOcean Spaces, please follow DigitalOceans official documentation.

2. Plug-in the route to sign uploads

(ns your.server
  (:require [s3-beam.handler :as s3b]
            [compojure.core :refer [GET defroutes]]
            [compojure.route :refer [resources]]))

(def bucket "your-bucket")
(def aws-zone "eu-west-1")
(def access-key "your-aws-access-key")
(def secret-key "your-aws-secret-key")

(defroutes routes
  (resources "/")
  (GET "/sign" {params :params} (s3b/s3-sign bucket aws-zone access-key secret-key)))

If you want to use a route different than /sign, define it in the handler, (GET "/my-cool-route" ...), and then pass it in the options map to s3-pipe in the frontend.

If you are serving your S3 bucket from DigitalOcean Spaces, with CloudFront, or another CDN/proxy, you can pass upload-url as a fifth parameter to s3-sign, so that the ClojureScript client is directed to upload through this bucket. You still need to pass the bucket name, as the policy that is created and signed is based on the bucket name.

3. Integrate the upload pipeline into your frontend

In your frontend code you can now use s3-beam.client/s3-pipe. s3-pipe's argument is a channel where completed uploads will be reported. The function returns a channel where you can put File objects of a file map that should get uploaded. It can also take an extra options map with the previously mentioned :server-url like so:

(s3/s3-pipe uploaded {:server-url "/my-cool-route"}) ; assuming s3-beam.client is NS aliased as s3

The full options map spec is:

If you choose to place a file map instead of a File object, you file map should follow:

An example using it within an Om component:

(ns your.client
  (:require [s3-beam.client :as s3]
  ...))

(defcomponent upload-form [app-state owner]
  (init-state [_]
    (let [uploaded (chan 20)]
      {:dropped-queue (chan 20)
       :upload-queue (s3/s3-pipe uploaded)
       :uploaded uploaded
       :uploads []}))
  (did-mount [_]
    (listen-file-drop js/document (om/get-state owner :dropped-queue))
    (go (while true
          (let [{:keys [dropped-queue upload-queue uploaded uploads]} (om/get-state owner)]
            (let [[v ch] (alts! [dropped-queue uploaded])]
              (cond
               (= ch dropped-queue) (put! upload-queue v)
               (= ch uploaded) (om/set-state! owner :uploads (conj uploads v))))))))
  (render-state [this state]
    ; ....
    )

Return values

The spec for the returned map (in the example above the returned map is v):

Or, if an error occurs during upload processing, an error-map will be placed on the response channel:

If :progress-events? are set to true, it will also forward those events from XhrIo:

Changes

0.6.0-alpha5

0.6.0-alpha4

0.6.0-alpha3

0.6.0-alpha1

0.5.2

0.5.1

0.4.0

0.3.1

0.3.0

0.2.0

Contributing

Pull requests and issues are welcome. There are a few things I'd like to improve:

Maintainers

Martin Klepsch Daniel Compton

License

Copyright © 2014 Martin Klepsch

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.