Skip to content

Instantly share code, notes, and snippets.

@pedroaxl
Last active February 28, 2016 05:21

Revisions

  1. pedroaxl revised this gist Nov 4, 2013. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion uploader.js.coffee
    Original file line number Diff line number Diff line change
    @@ -26,7 +26,6 @@ SirTrevor.fileUploader = (block, file, success, error) ->
    data: {
    file_name: file.name
    file_type: file.type
    md5: file.md5
    }
    type: 'GET'
    error: callbackError
  2. pedroaxl created this gist Nov 4, 2013.
    22 changes: 22 additions & 0 deletions config_controller.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,22 @@
    # As we cant make Secret Access Key open, this method generates a signature that will allow the user to upload this
    # file specifically

    def sign_s3
    bucket_name = 'mailee-images'
    original_name = params['file_name']
    original_extension = original_name.split('.').last
    mime_type = params['file_type']
    object_name = Time.now.to_f.to_s.gsub('.','') + '.' + original_extension
    #TODO return unless mime_type is valid
    date = Time.now.utc.iso8601.gsub(/-|:/,'')
    amazon_headers = ["x-amz-acl:public-read","x-amz-date:#{date}"] # set the public read permission on the uploaded file
    string_to_sign = "PUT\n\n#{mime_type}\n\n#{amazon_headers[0]}\n#{amazon_headers[1]}\n/#{bucket_name}/#{current_client.id}/#{object_name}";
    signature = Base64.strict_encode64(OpenSSL::HMAC.digest('sha1', APP_CONFIG['aws_secret_access_key'], string_to_sign))
    path = "https://s3.amazonaws.com/#{bucket_name}/#{current_client.id}/#{object_name}"
    r = {
    signature: "AWS #{APP_CONFIG['aws_access_key_id']}:#{signature}",
    date: date,
    url: path,
    }
    render json: r
    end
    53 changes: 53 additions & 0 deletions uploader.js.coffee
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,53 @@
    #
    #* Sir Trevor Uploader
    #* Generic Upload implementation that can be extended for blocks
    #
    #* modified by @pedroaxl to upload directly to S3

    SirTrevor.fileUploader = (block, file, success, error) ->
    SirTrevor.EventBus.trigger "onUploadStart"
    uid = [block.blockID, (new Date()).getTime(), "raw"].join("-")

    block.resetMessages()
    callbackSuccess = (data, textStatus, jqXHR) ->
    SirTrevor.log "Upload callback called"
    SirTrevor.EventBus.trigger "onUploadStop"
    # once the PUT response from Amazon comes empty, I had to change this line to include the url
    _.bind(success, block) {file: this.url} if not _.isUndefined(success) and _.isFunction(success)

    callbackError = (jqXHR, status, errorThrown) ->
    SirTrevor.log "Upload callback error called"
    SirTrevor.EventBus.trigger "onUploadStop"
    _.bind(error, block) status if not _.isUndefined(error) and _.isFunction(error)

    $.ajax(
    url: '/config/sign_s3'
    # before sending to Amazon using PUT, it makes a req to get the signature that will allow the upload
    data: {
    file_name: file.name
    file_type: file.type
    md5: file.md5
    }
    type: 'GET'
    error: callbackError
    success: (data, textStatus, jqXHR) ->
    xhr = $.ajax(
    url: data.url
    contentType: file.type
    crossDomain: true
    data: file
    processData: false
    headers: {
    'Content-MD5': file.md5
    'Authorization': data.signature
    'x-amz-date': data.date
    'x-amz-acl': 'public-read' # set the public read permission on the uploaded file
    }
    type: "PUT"
    success: callbackSuccess
    )
    block.addQueuedItem uid, xhr
    xhr.done(callbackSuccess).fail(callbackError).always _.bind(block.removeQueuedItem, block, uid)
    xhr
    )