Skip to content

Instantly share code, notes, and snippets.

@schneems
Last active October 22, 2017 14:44
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save schneems/ebb7b1de4b23e1e7a27e to your computer and use it in GitHub Desktop.
Save schneems/ebb7b1de4b23e1e7a27e to your computer and use it in GitHub Desktop.
AWS.config(access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'] )
S3_BUCKET = AWS::S3.new.buckets[ENV['S3_BUCKET']]
.progress {
max-width: 600px;
margin: 0.2em 0 0.2em 0;
}
.progress .bar {
height: 1.2em;
padding: 0.2em;
color: white;
display: none;
}
# GET /users/new
def new
@s3_direct_post = S3_BUCKET.presigned_post(
key: "uploads/#{SecureRandom.uuid}/${filename}",
acl: :public_read,
success_action_status: 201)
@user = User.new
end
<!-- ... -->
<%= form_for(@user, html: { class: "directUpload" }) do |f| %>
<% if @user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :avatar_url %><br>
<%= f.file_field :avatar_url %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<script>
$(function() {
$('.directUpload').find("input:file").each(function(i, elem) {
var fileInput = $(elem);
var form = $(fileInput.parents('form:first'));
var submitButton = form.find('input[type="submit"]');
var progressBar = $("<div class='bar'></div>");
var barContainer = $("<div class='progress'></div>").append(progressBar);
fileInput.after(barContainer);
fileInput.fileupload({
fileInput: fileInput,
url: '<%= @s3_direct_post.url %>',
type: 'POST',
autoUpload: true,
formData: <%= @s3_direct_post.fields.to_json.html_safe %>,
paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
dataType: 'XML', // S3 returns XML if success_action_status is set to 201
replaceFileInput: false,
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
progressBar.css('width', progress + '%')
},
start: function (e) {
console.log('Started');
submitButton.prop('disabled', true);
progressBar.
css('background', 'green').
css('display', 'block').
css('width', '0%').
text("Loading...");
},
done: function(e, data) {
console.log('Done');
submitButton.prop('disabled', false);
progressBar.text("Uploading done");
// extract key and generate URL from response
var key = $(data.jqXHR.responseXML).find("Key").text();
var url = '//<%= @s3_direct_post.url.host %>/' + key;
// create hidden field
var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url })
form.append(input);
},
fail: function(e, data) {
console.log("Failed");
progressBar.
css("background", "red").
text("Failed");
}
});
});
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment