如何正确地将对象上传到AWS S3? [英] How to properly upload an object to AWS S3?

查看:261
本文介绍了如何正确地将对象上传到AWS S3?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

追逐此问题三天后.是时候寻求帮助了. 我有一个签名的URL,可以将文件上传到Amazon S3.我知道这是正确的,因为

After three days of chasing this problem. It's time to ask for some help. I have a signed url to upload a file to Amazon S3. I know this is correct, since a

curl -v -T file.png --header "Content-Type:binary/octet-stream" "https://sample.s3.amazonaws.com/33d7e8f0-0fc5-11e5-9d95-2b3410860edd?AWSAccessKeyId=XXXXXXXX&Content-Type=binary%2Foctet-stream&Expires=1433984735&Signature=LUjj8iIAbCfNoskGhqLDhuEWVG4%3D"

成功完成.

但是我执行上传的.ajax代码(如下)使内容在S3存储桶中略有乱码.
例如,如果我上传一个.pdf文件,则可以从S3管理控制台正确加载该文件,但是如果它是.png或.jpeg等文件,则它将失败.

But my .ajax code (below) which does the upload leaves the content garbled slightly in the S3 bucket.
For example if I upload a .pdf file, it loads properly from the S3 Management Console, but if it is a .png or .jpeg, etc. it fails... And looking closely the file has the wrong length (slightly).

浏览器中通话的重点是:

The heart of the call in the browser is:

var formData = new FormData();
formData.append("upload", file);
$.ajax({ url: data.puturl,
         type: 'PUT',
         xhr: function() {
           var myXhr = $.ajaxSettings.xhr();
           if (myXhr.upload) {
             myXhr.upload.addEventListener('progress', progressHandlingFunction, 
                                           false);
           }
           return myXhr;
         },
         success: completeHandler,
         error: errorHandler,
         data: formData,
         cache: $.param(false),
         contentType: "binary/octet-stream",
         processData: $.param(false)
         }, 'json');

这似乎几乎可以正常工作,但是数据显示为乱码.我尝试将内容设置为file.type等,但无济于事.我需要在这里进行一些编码吗?如我所缺少的base64 ??

This almost seems to work, but the data is garbled. I have tried setting the content to file.type, etc. to no avail. Is there some encoding that I need to do here? Such as base64 that I am missing????

任何见识将不胜感激.
或者,如果有一种简便的方法可以不使用.ajax来执行相同的操作,那将是很好的.

Any insight would be greatly appreciated.
OR if there is an easy way to not use .ajax to do the same thing, that would be great.

推荐答案

从上面'tedder42'提出的问题以及更多的实验中,我意识到发送FormData是问题.因此,我将代码更改为仅使用FileReader()并传递原始数据.这完美地工作.这是代码:

From the question that 'tedder42' asked above, and some more experimentation, I realized that sending the FormData was the issue. So I changed the code to just use a FileReader() and pass the raw data. This works perfectly. Here is the code:

var reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function (e) {
  var rawData = reader.result;
  $.ajax({ url: data.puturl,
    type: 'PUT',
    xhr: function() {
      var myXhr = $.ajaxSettings.xhr();
      if (myXhr.upload) {
        myXhr.upload.addEventListener('progress', progressHandlingFunction, false);
      }
      return myXhr;
    },
    success: completeHandler,
    error: errorHandler,
    // Form data
    data: rawData,
    cache: $.param(false),
    contentType: "binary/octet-stream",
    processData: $.param(false)
  }, 'json');
};

这更加简单明了,并且一切正常.然后,当稍后使用签名的URL下载数据时,我只需输入

This is much more straightforward and everything works perfectly. Then when the data is downloaded later using a signed url, I simply put

ResponseContentDisposition: "attachment; filename="+fileData.name

作为s3.getSignedUrl('getObject',params)调用中的参数之一.

as one of the params in the s3.getSignedUrl('getObject', params) call.

然后在预先签名的url中检索文件,

AND in the presigned url to retrieve the file, I put

ResponseContentDisposition: "attachment; filename="+fileData.name, 'ResponseContentType': fileData.type 

负责确保浏览器期望收到的内容.

which takes care of ensuring that the browser expects what it is receiving.

由于在使用预签名的url时上传对象时无法设置内容类型,因此我还在服务器端添加了代码,以在上传完成后更改对象的内容类型.这是代码的核心:

Because you cannot set the content-type when uploading the object when using a pre-signed url, I also added code on the server side to change the object content-type after the upload has completed. Here is the heart of the code:

var params = {
  Bucket: 'sample',
  CopySource: 'sample/' + file.key,
  Key: file.key,
  MetadataDirective: 'REPLACE',
  ContentType: type
};
s3.copyObject(params, function (err, data){
  if (err) {
    console.log(err);
    validationError(res, 'unable to change content-type!');
  }
  res.sendStatus(200);
});

这很难使人正确,我希望这对其他人有帮助!

This was a pain to finally get right and I am hopeful that this will help others!

这篇关于如何正确地将对象上传到AWS S3?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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