score:0

Accepted answer

In the add: callback change your s3 signature for the 'key' from '/somefolder/${filename}' to '/somefolder/your-new-name'

s3_signatures = { 
                  key: '/somefolder/${filename}',
                  …
                }

$('.fileupload').fileupload({
  url: url,
  type: 'POST',
  formData: s3_signatures, // adding signature for S3
  add: function(e, data){
    s3_signatures['key'] = '/somefolder/your-new-name';
    data.formData = s3_signatures;
    data.submit();
  } …

score:2

I ran into a similar challenge after following the Heroku tutorial. I wanted to remove spaces from the filename and add a folder prefix based on the current project. In order to change the filename before uploading to S3, I added a submit callback where I modified the name on the client side.

fileInput.fileupload({
    ...
    submit: function (e, data) {
        // Get the original filename
        var fileName = data.originalFiles[0].name
        // Get the prefix from the form 
        var keyPrefix = form.data('key-start')
        // Combine the prefix and the original filename with start/end whitespace removed
        var fullFileName = keyPrefix + fileName.trim();
        // Replace whitespaces with underscores
        // At this step you could replace other special characters as well
        var newFileName = fullFileName.replace(/\s+/g, '_');
        // Update the form data with the new key value
        $(form.data('form-data')).attr("key", newFileName);
        // Set the form data
        data.formData = form.data('form-data');
    },
    ...
});

Since I changed the filename, I needed to ensure that S3 knows that as well. The tutorial suggested key value in the controller set_s3_direct_post method is:

key: "uploads/#{SecureRandom.uuid}/${filename}"

The key method requires that the filename match what is provided when the post URL is created (which it wouldn't because I'm not using the dynamic ${filename} value and I don't know the final filename when the direct post URL is created to specify it). I used the key_starts_with method so that I could specify the project folder prefix (with spaces removed) and S3 would just evaluate that for a match:

key_starts_with: "#{(current_project.name).strip.split(' ').join('_')}/"

My final set_s3_direct_post method was:

def set_s3_direct_post
    @s3_direct_post = S3_BUCKET.presigned_post(key_starts_with: "#{(current_project.name).strip.split(' ').join('_')}/", success_action_status: '201', acl: 'public-read')
end

More details on key_starts_with can be found in the AWS SDK for Ruby.

For reference, here is my form with the added key-start data value:

<%= simple_form_for @asset, html: {class: 'directUpload new_asset', data: { 'form-data' => (@s3_direct_post.fields), 'key-start' => "#{current_project.name}/#{SecureRandom.hex(4)}_" , 'url' => @s3_direct_post.url, 'host' => URI.parse(@s3_direct_post.url).host  } } , :url => project_assets_path(current_project) do |f| %>
    <%= f.input :name %>
    <%= f.input :file, as: :file %>
    <%= f.button :submit, "Add File", class: "addFileButton" %>
<% end %> 

In my case, I was only using this for single file uploads and only wanted to ensure spaces were removed from the filename (I was one of two users of this upload form, so special characters or other issues with the filename weren't a concern).


Related Query

More Query from same tag