简体   繁体   English

S3 putObject使用AWS-SDK失败

[英]S3 putObject fails using aws-sdk

It's driving me crazy, any help would be much appreciated! 这让我发疯,任何帮助将不胜感激!

To set up my bucket in S3 I followed http://www.cheynewallace.com/uploading-to-s3-with-angularjs/ 要在S3中设置存储桶,我遵循了http://www.cheynewallace.com/uploading-to-s3-with-angularjs/

Regarding this post I made following "improvements" by extended the policy with a wildcard and giving more rights 关于此帖子,我通过“通配符”扩展了政策并给予了更多权利,从而在“改进”之后

{
"Version": "2012-10-17",
"Statement": [
    {
        "Effect": "Allow",
        "Action": [
            "s3:DeleteObject",
            "s3:DeleteObjectVersion",
            "s3:GetObject",
            "s3:GetObjectAcl",
            "s3:GetObjectTorrent",
            "s3:GetObjectVersion",
            "s3:GetObjectVersionAcl",
            "s3:GetObjectVersionTorrent",
            "s3:PutObject",
            "s3:PutObjectAcl",
            "s3:PutObjectVersionAcl"
        ],
        "Resource": [
            "arn:aws:s3:::photos-eu/*"
        ]
    }
]
}

and added < ExposeHeader>ETag< /ExposeHeader > to the Cors settings of the bucket 并将<ExposeHeader> ETag </ ExposeHeader>添加到存储桶的Cors设置

Then my angular service using the aws-sdk look like 然后我使用aws-sdk的角度服务看起来像

/// <reference path="../../../typings/tsd.d.ts" />

module Services {

  export interface IS3UploadService {
    upload(imgName:string, imgData:string):ng.IPromise<{}>;
  }

  export class S3UploadService implements IS3UploadService {

static $inject = ['$q'];

private bucket:AWS.S3;

constructor(private $q:ng.IQService) {
  var credentials = new AWS.Credentials("myAccessKeyId", "mySecretAccessKey");
  AWS.config.update(credentials);
  AWS.config.region = "eu-west-1";

  this.bucket = new AWS.S3({params: {Bucket: 'peterparker-photos-eu', maxRetries: 10, region: "eu-west-1"}});

}

upload(imgName:string, imgData:string):ng.IPromise<{}> {
  var deferred = this.$q.defer();

  var params:AWS.s3.PutObjectRequest = {
    Bucket: "peterparker-photos-eu",
    Key: imgName,
    Body: imgData,
    ContentType: "image/jpeg",
    ContentEncoding: "Base64"
  };

  this.bucket.putObject(params, (err:any, data:any) => {
    if (err) {
      console.error("->" + JSON.stringify(err));
      deferred.reject(err);
    } else {
      console.info(data);
      deferred.resolve(data);
    }
  });

  return deferred.promise;
}

  }
}

angular.module('App')
  .service('S3UploadService', Services.S3UploadService);

For my test purpose, I push in the imgData an img encoded as Base64, something like "/9j/4AAQSkZJRgABAgAAZABkA...." (of course a valid image converted with http://base64-image.de ) 为了测试目的,我将imgData编码为Base64,例如“ / 9j / 4AAQSkZJRgABAgAAZABkA ....”(当然,这是用http://base64-image.de转换的有效图像)

And as result, each time I try, I've got following error 结果,每次我尝试时,都会遇到以下错误

{"line":25,"column":24996,"sourceURL":" http://localhost:8100/lib/aws-sdk/dist/aws-sdk.min.js ","message":"The request signature we calculated does not match the signature you provided. Check your key and signing method.","code":"SignatureDoesNotMatch","region":null,"time":"2016-06-08T15:12:09.945Z","requestId":null,"statusCode":403,"retryable":false,"retryDelay":60.59883770067245} {“ line”:25,“ column”:24996,“ sourceURL”:“ http:// localhost:8100 / lib / aws-sdk / dist / aws-sdk.min.js ”,“ message”:“请求我们计算出的签名与您提供的签名不匹配。请检查您的密钥和签名方法。“,”代码“:” SignatureDoesNotMatch“,” region“:null,” time“:” 2016-06-08T15:12:09.945Z“ ,“ requestId”:空,“ statusCode”:403,“ retryable”:false,“ retryDelay”:60.59883770067245}

So much fun... 玩得很尽兴...

Update headers: 更新标题:

General
Request URL:https://peterparker-photos-eu.s3-eu-west-1.amazonaws.com/1465408512724.jpg
Request Method:PUT
Status Code:403 Forbidden
Remote Address:54.231.131.16:443

Response headers
Access-Control-Allow-Methods:HEAD, GET, PUT, POST, DELETE
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:ETag, x-amz-meta-custom-header
Connection:close
Content-Type:application/xml
Date:Wed, 08 Jun 2016 17:55:20 GMT
Server:AmazonS3
Transfer-Encoding:chunked
Vary:Origin, Access-Control-Request-Headers, Access-Control-Request-        Method
x-amz-id-...
x-amz-request-id:...

Request Headers
Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,de;q=0.2
Authorization:AWS ...
Connection:keep-alive
Content-Encoding:Base64
Content-Length:38780
Content-MD5:...
Content-Type:image/jpeg; charset=UTF-8
Host:peterparker-photos-eu.s3-eu-west-1.amazonaws.com
Origin:http://localhost:8100
Referer:http://localhost:8100/?ionicplatform=ios
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5)             AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36
X-Amz-Date:Wed, 08 Jun 2016 17:55:20 GMT
X-Amz-User-Agent:aws-sdk-js/2.3.18

Request payload
Img base64 code

Update 更新资料

Even by trying to upload a non Base64 content it finish with the same error 即使尝试上传非Base64内容,它也会出现相同的错误

var paramsHtml:AWS.s3.PutObjectRequest = {
    Bucket: "peterparker-photos-eu",
    Key: "HelloWorld.html",
    Body: "The Body",
    ContentType: "text/html"
  };

Update #2 更新#2

I moved to a solution with a signed URL generated by my node js server as described in following solution, still got the same error as result...but I least I try ;) 我转移到一个解决方案,该解决方案具有节点js服务器生成的签名URL(如以下解决方案中所述),但仍然收到与结果相同的错误...但是我至少要尝试;)

upload file from angularjs directly to amazon s3 using signed url 使用签名的URL将文件从angularjs直接上传到Amazon s3

Freak I finally find the solution or at least a solution. 我终于找到了解决方法,或者至少是解决方法。

After migrating my client aws-sdk based solution to a solution where the server generate a signedUrl I was still facing the same error. 在将基于客户端aws-sdk的客户端解决方案迁移到服务器生成SignedUrl的解决方案之后,我仍然面临着同样的错误。 Short story long, it fixed the problem by setting in both side the Content-type for the header. 长话短说,它通过在两边设置标题的Content-type来解决此问题。

My code if someone face the same problem one day: 如果某人一天遇到相同问题,我的代码:

Server Node.js 服务器Node.js

var AWS = require('aws-sdk');

AWS.config.update({accessKeyId: "myKey", secretAccessKey: "mySecret"});
AWS.config.region = 'eu-west-1';

app.post('/api/images', securityPolicy.authorise, function (req, res) {

var s3 = new AWS.S3();

var imgName = req.body.imgName;
var contentType = req.body.contentType;

// Expires in seconds
var params = {Bucket: 'photos-eu', Key: imgName, Expires: 600, ContentType: contentType};
s3.getSignedUrl('putObject', params, function (err, url) {
    if (err) {
        res.status(500).json({
            error: "Presigned S3 url for putObject can't be created. " + JSON.stringify(err)
        });
    } else {
        res.json({url: url});
    }
});
});

Client angular: 客户角度:

  • First or course there is the part to call the node server, obvious POST to my server 首先或当然有一部分可以调用节点服务器,对我的服务器进行明显的POST

And then the second part processing the signedURL 然后第二部分处理signedURL

private uploadToS3(preSignedUrl:string, imgData:string):ng.IPromise<{}> {
  var deferred = this.$q.defer();

  // Post image to S3
  this.$http({
    method: 'PUT',
    url: preSignedUrl,
    headers: {'Content-Type': 'image/jpeg'},
    data: imgData
  })
    .then((response:any) => {
      console.log("Image uploaded to S3" + JSON.stringify(response));

      deferred.resolve();

    }, (response:any) => {
      console.log("Error Presigned URL" + JSON.stringify(response));
      deferred.reject(response);
    });

  return deferred.promise;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM