s3-beam is a Clojure/Clojurescript library designed to help you upload files
from the browser to S3 (CORS upload).
[org.martinklepsch/s3-beam "0.3.0"]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:
- A pluggable route that will send back the required parameters for a given file-name & mime-type
- 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
Please follow Amazon's official documentation.
(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 "s3-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.
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 that should get uploaded. It might also take an extra options
map with the previously mentioned :server-url like so:
(s3/s3-pipe uploaded {:server-url "/my-cool-route"})
An example using it within an Om component:
(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]
; ....
)The uploaded channel will return a map with the :file object that
was uploaded and a :response map that contains the :location,
:bucket, :key, and :etag of the file in S3.
- Added the
:key-fnoptions3-beam.handler/sign-uploadto generate custom S3 keys fromfile-nameandmime-type. - Breaking Change: the
uploadedchannel now returns a map with the:filethat was uploaded and the S3:responsemap with itself contains all the information necessary to locate the file in S3::location,:key,:bucket, and:etaginstead of just the location as a string.
-
Allow customization of server-side endpoint (1cb9b27)
(s3/s3-pipe uploaded {:server-url "/my-cool-route"})
- Allow passing of
aws-zoneparameter tos3-signhandler function. (b880736)
Pull requests and issues are welcome. There are a few things I'd like to improve:
- Testing: currently there are no tests
- Custom route: allow use of other routes than
/sign - Error handling: what happens when the request fails?
- Upload progress: XhrIo supports
PROGRESSevents and especially for larger uploads it'd be nice to have them
Copyright 漏 2014 Martin Klepsch
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.