使用Rails和jQuery文件上传设置内容类型直接到S3上传 [英] Setting the Content-Type in direct to S3 upload using Rails and jQuery File Upload

查看:234
本文介绍了使用Rails和jQuery文件上传设置内容类型直接到S3上传的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我见过很多问题在这里就这个话题,但没有我遇到很适合我,所以我在这里张贴的另一个...

I've seen many questions here on this topic but nothing I've come across has worked for me, so here I am posting another...

我在Ruby on Rails的尝试配置文件上传直接到Amazon S3使用 jQuery的文件上传插件。我跟着一起非常有帮助 Heroku的教程获取初始设置加工。上传的文件很好,但他们都被标记为内容类型:二进制/八位字节流在S3中,所以当他们曾在应用程序中,所有的文件会下载,而不是直接打开。

I'm on Ruby on Rails trying to configure file uploads direct to Amazon S3 using the jQuery File Upload plugin. I followed along with the very helpful Heroku tutorial to get the initial setup working. Files uploaded fine, but they were all labeled as Content-Type: binary/octet-stream in S3, so when they were served in the app, all files would download instead of opening directly.

这是一个问题,因为我试图让图像,PDF文件,音频或视频文件,所以我需要能够抓住正确的内容类型从该文件,并把它传递给S3。在看在亚马逊的AWS-SDK宝石文档,我看到了<一个href="http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/S3/$p$psignedPost.html#where-instance_method">this部分有关添加。凡(:CONTENT_TYPE).starts_with()至presigned后对象的末尾修改政策。然而,当我这样做,它抛出一个错误:

This is a problem because I'm trying to allow images, PDFs, audio or video files, so I need to be able to grab the correct Content-Type from the file and pass it on to S3. In looking at the AWS-SDK gem docs on Amazon, I saw this section about adding .where(:content_type).starts_with("") to the end of the presigned post object to modify the policy. However, when I did that, it threw an error:

<Error><Code>AccessDenied</Code>
<Message>Invalid according to Policy: Policy Condition failed: ["starts-with", "$Content-Type", ""]</Message>

所以我加入 CONTENT_TYPE:进入OPTS哈希为presigned post对象,而现在它的作品了,但不是所有的文件默认为二进制/八位字节流都默认为为image / jpeg 。这是我的code截至目前:

So I added in content_type: "" into the opts hash for the presigned post object, and now it works again, but instead of all files defaulting to binary/octet-stream they all default to image/jpeg. Here's my code as of now:

控制器

def new
  @s3_direct_post = S3_BUCKET.presigned_post(
                  key: "uploads/#{SecureRandom.uuid}/${filename}",
                  success_action_status: 201,
                  acl: :public_read,
                  content_type: "").where(:content_type).starts_with("")
end

_form.html.haml

:javascript
  $(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);
      var fd           = #{@s3_direct_post.fields.to_json.html_safe};
      fileInput.after(barContainer);
      fileInput.fileupload({
        // This 'add' section is where I thought to set the Content-Type, but I've tried  with and without it and Content-Type remains the same on S3
        add: function (e, data) {
          fd["Content-Type"] = data.files[0].type;  
          console.log(fd);    // The JSON object shows Content-Type correctly in console
          data.submit();
        },  
        fileInput:        fileInput,
        url:              '#{@s3_direct_post.url}',
        type:             'POST',
        autoUpload:       true,
        formData:         fd,   // My updated JSON object
        paramName:        'file',
        dataType:         'XML',
        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);

          progressBar.
            css('background', 'green').
            css('display', 'block').
            css('width', '0%').
            text("Loading...");
        },
        done: function(e, data) {
          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   = 'https://d295xbrl26r3ll.cloudfront.net/' + key.replace(/ /g, "%20");

          // create hidden field
          var input = $("<input />", { type:'hidden', name: 'item[file_url]', value: url })
          form.append(input);
        },
        fail: function(e, data) {
          submitButton.prop('disabled', false);

          progressBar.
            css("background", "red").
            text("Failed");
        }
      });
    });
  });

我如何发送内容类型妥善S3?

推荐答案

替换为你加挡:

      fd["Content-Type"] = data.files[0].type;  
      data.formData = fd;
      data.submit();

回调是正确的,但data.formData已经采取了FD的原始版本。只要重新设置与修改后的FD,你应该是好去。

The callback is correct, but data.formData already took the original version of fd. Just set it again with your modified fd and you should be good to go.

更新控制方法也让你不这样做了两遍:

Update the controller method too so you're not doing it twice:

@s3_direct_post = S3_BUCKET.presigned_post(
                  key: "uploads/#{SecureRandom.uuid}/${filename}",
                  success_action_status: 201,
                  acl: :public_read).where(:content_type).starts_with("")

这篇关于使用Rails和jQuery文件上传设置内容类型直接到S3上传的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆