Rails中的多个直接到S3图像上传

时间:2017-11-04 17:34:46

标签: ruby-on-rails heroku amazon-s3

我跟着this Heroku tutorial直接上传带有S3的Rails上传图片。

我的实施效果很好。但是,我动态添加包含图片上传字段的Cocoon gem字段。因此,我的目标是能够使用Heroku的方法上传多个图像,以便直接上传。

这是我的javascript代码:

$('.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:             form.data('url'),
        type:            'POST',
        autoUpload:       true,
        formData:         form.data('form-data'),
        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) {
          submitButton.prop('disabled', true);
          insertedItem.find('#validate_image').css('opacity', '0.3');
          insertedItem.find('#validate_image').prop('disabled', true);
          progressBar.
            css('background', '#11D26F').
            css('display', 'block').
            css('width', '0%').
            text("Loading...");
        },
        done: function(e, data) {
          submitButton.prop('disabled', false);
          insertedItem.find('#validate_image').css('opacity', '1');
          insertedItem.find('#validate_image').prop('disabled', false);
          progressBar.text("Uploading done");

          // extract key and generate URL from response
          var key   = $(data.jqXHR.responseXML).find("Key").text();
          var url   = 'https://' + form.data('host') + '/' + key;

          // create hidden field
          var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url })
          form.append(input);
        },
        fail: function(e, data) {
          submitButton.prop('disabled', false);
          if (data['messages']['uploadedBytes'] == 'Uploaded bytes exceed file size') {
            progressBar.
              css("background", "red").
              text("Uploaded file is too big (max 3.5 MB)");
          }
          else {
            progressBar.
              css("background", "red").
              text("Failed");
          }
        }
      });
    });

问题是,每次上传新文件时,它都会在表单末尾添加一个隐藏字段,并使用相同的图片网址。我想每次为上传的图片生成一个新网址。

我搜索了几个小时的解决方案,但找不到解决方案。知道如何使用Heroku方法吗?

1 个答案:

答案 0 :(得分:0)

好的,所以我这样破解了我的方式: 由于我只想上传最多10张图片,因此我生成了10个不同的presigned_posts:

def set_s3_direct_post
      @s3_direct_post1 = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}", success_action_status: '201', acl: 'public-read', content_length_range: 0..3500000)
      @s3_direct_post2 = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}", success_action_status: '201', acl: 'public-read', content_length_range: 0..3500000)
      @s3_direct_post3 = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}", success_action_status: '201', acl: 'public-read', content_length_range: 0..3500000)
      @s3_direct_post4 = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}", success_action_status: '201', acl: 'public-read', content_length_range: 0..3500000)
      @s3_direct_post5 = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}", success_action_status: '201', acl: 'public-read', content_length_range: 0..3500000)
      @s3_direct_post6 = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}", success_action_status: '201', acl: 'public-read', content_length_range: 0..3500000)
      @s3_direct_post7 = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}", success_action_status: '201', acl: 'public-read', content_length_range: 0..3500000)
      @s3_direct_post8 = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}", success_action_status: '201', acl: 'public-read', content_length_range: 0..3500000)
      @s3_direct_post9 = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}", success_action_status: '201', acl: 'public-read', content_length_range: 0..3500000)
      @s3_direct_post10 = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}", success_action_status: '201', acl: 'public-read', content_length_range: 0..3500000)
    end

然后我使用一些javascript将表单数据移动到动态生成的容器中。

有效!