SignatureDoesNotMatch $ cordovaFileTransfer

我试图上传一个video到以前用$cordovaCapture录制的Amazon s3

捕获进程正常工作,作为响应,我得到的object

 [MediaFile] 0: MediaFileend: 0 fullPath: "file:/storage/sdcard/DCIM/Camera/VID_20160919_144041.mp4" lastModified: null lastModifiedDate: 1474288843000 localURL: "cdvfile://localhost/persistent/DCIM/Camera/VID_20160919_144041.mp4" name: "VID_20160919_144041.mp4" size: 17098 start: 0 type: "video/mp4" __proto__: utils.extend.F length: 1 __proto__: Array[0] 

然后,在我上传video之前,我向服务器请求身份validationURL ,如下所示:

的NodeJS

 getSignedUrl: function (filename, type, callback) { if (filename) { AWS.config.update({ accessKeyId: 'my_access_key', secretAccessKey: 'my_secret_access_key', region: 'my_region' }); var s3 = new AWS.S3(); s3.getSignedUrl('putObject', {Bucket: 'my_bucket', Key: 'uploads/' + filename, ContentType: type}, function (err, url) { if (err) { callback(err); } else { callback(url); } }); } else { callback('Error'); } } 

这给了我下一个端点:

 https://s3-my_region.amazonaws.com/my_bucket/uploads/VID_20160919_144…=video%2Fmp4&Expires=1474289746&Signature=sF67ukPu3oELJXzsmAXCeeEJ%2FE4%3D 

当我得到指向我上传的URL后,问题就在这里:

有这样的代码:

 var options = { httpMethod: "PUT", fileName: name, mimeType: type, chunkedMode: 'false', encodedURI: 'false', headers: { "Content-Type": type } }; $cordovaFileTransfer.upload(url, videoPath, options) .then(function (result) { callback(result); }, function (err) { callback(err); }, function (progress) { p = progress; }); 

这是我得到的错误:

 http status: 403 Code: 1 description: <?xml version="1.0" encoding="UTF-8"?> <Error> <Code>SignatureDoesNotMatch</Code> <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message> <AWSAccessKeyId>my_access_key</AWSAccessKeyId> <StringToSign> PUT video/mp4 1474291133 /my_bucket/uploads/VID_20160919_150347.mp4 </StringToSign> <SignatureProvided> nwLEVBOarxi7YwyB4hJ2op4j1ms%253D </SignatureProvided> <StringToSignBytes> 50 55 54 0a 0a 76 69 64 65 6f 2f.... </StringToSignBytes> <RequestId>CC29DD761826BAFF</RequestId> <HostId> OHTLyBaAa29X04msYXqwmvr1Mw90wnPmkxXeU7pTOb9pFwDuuRXDC3AdLNwVIoEHnoUEsceWn24= </HostId> </Error> 

听起来像问题是在header周围,​​这并不像预期的那样工作。

另外,我直接在cordova-plugin-file-transfer的文档中尝试了第二个选项code

 var options = new FileUploadOptions(), ft = new FileTransfer(); options.httpMethod = "PUT"; options.fileName = name; options.mimeType = type; options.headers = { ContentType: type }; options.chunkedMode = "false"; options.encodeURI = "false"; ft.upload(videoPath, url, callback, callback, options); 

具有相同的响应错误。

这里我也遇到了Content-Type问题。 即使在文档中声明像:

 var headers = { "Content-Type": 'video/mp4' }; options.headers = headers; 

它正在返回我的下一个错误:

 http status: 501 description: <?xml version="1.0" encoding="UTF-8"?> <Error> <Code>NotImplemented</Code> <Message> A header you provided implies functionality that is not implemented </Message> <Header>Transfer-Encoding</Header> <RequestId>231F38AFFBB587C6</RequestId> . . . </Error> 

就像我注意到的那样,我使用了$http.post就像在我的这个其他职位上一样。

UPDATE

在这个问题上进行了更多的调查,使用nodeJS代码我也无法上传任何东西,所以我只是像这样修改了S3构造函数:

 s3 = new AWS.S3({ signatureVersion: 'v4', region: "us-west-2" }); 

之后,像这样通过控制台检查curl

 curl -v -H "Content-Type: application/octet-stream" --upload-file "/Users/my_user/Desktop/VID_20160920_233443.mp4" "https://s3-us-west-2.amazonaws.com/my_bucket/uploads/VID_20160920_233443.mp4?Content-Type=video%2Fmp4&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJV3UP7LBEKPYMLGA%2F20160921%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20160921T103723Z&X-Amz-Expires=600&X-Amz-Signature=8463625a45237452280b3dc9cfd89366093f7b78f8c76598ba2240f06c7f20c9&X-Amz-SignedHeaders=host%3Bx-amz-acl&x-amz-acl=public-read" 

回应成功:

 * Trying 54.231.176.22... * Connected to s3-us-west-2.amazonaws.com (54.231.176.22) port 443 (#0) * TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 * Server certificate: *.s3-us-west-2.amazonaws.com * Server certificate: DigiCert Baltimore CA-2 G2 * Server certificate: Baltimore CyberTrust Root > PUT /my_bucket/uploads/VID_20160920_233443.mp4?Content-Type=video%2Fmp4&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJV3UP7LBEKPYMLGA%2F20160921%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20160921T103723Z&X-Amz-Expires=600&X-Amz-Signature=8463625a45237452280b3dc9cfd89366093f7b78f8c76598ba2240f06c7f20c9&X-Amz-SignedHeaders=host%3Bx-amz-acl&x-amz-acl=public-read HTTP/1.1 > Host: s3-us-west-2.amazonaws.com > User-Agent: curl/7.43.0 > Accept: */* > Content-Type: application/octet-stream > Content-Length: 18964 > Expect: 100-continue > < HTTP/1.1 100 Continue * We are completely uploaded and fine < HTTP/1.1 200 OK < x-amz-id-2: moDxOsEISsfqjCILaIsJtl3ncc7UeH4hNNISiJeuH46MrDrHEfVm9EKC5RRkORMilDEE5z7l8cI= < x-amz-request-id: BC345E2AC71AC019 < Date: Wed, 21 Sep 2016 10:38:05 GMT < x-amz-expiration: expiry-date="Fri, 23 Sep 2016 00:00:00 GMT", rule-id="Delete bad uploads after 1 day" < ETag: "7688c487b1ea40c849fdb070cf736b28" < Content-Length: 0 < Server: AmazonS3 < * Connection #0 to host s3-us-west-2.amazonaws.com left intact 

改变这个新的angular码:

 var options = new FileUploadOptions(), ft = new FileTransfer(); options.httpMethod = "PUT"; options.fileKey = "file"; options.fileName = name; options.mimeType = type; options.chunkedMode = false; options.headers = { "Content-Type": type, "x-amz-acl": 'public-read' }; ft.upload(videoPath, url, callback(null), callback, options); 

问题依然存在:

 An error has occurred: Code = 1 upload error source cdvfile://localhost/persistent/DCIM/Camera/VID_20160921_122323.mp4 upload error target https://s3-us-west-2.amazonaws.com/my_bucket/uploads/VID_20160921_122…9e365af3f771c5d&X-Amz-SignedHeaders=host%3Bx-amz-acl&x-amz-acl=public-read http status: 501 description: <?xml version="1.0" encoding="UTF-8"?> <Error><Code>NotImplemented</Code><Message>A header you provided implies functionality that is not implemented</Message><Header>Transfer-Encoding</Header><RequestId>D646593FD109C0F8</RequestId><HostId>wVmGWPAAWdmSXdq5N/eO7ihqHk0GoMlXNe6k9sAyyEz55Q4k2gGgkgsgyXkh8xsxUDlmzQdAIPQ=</HostId></Error> 

这里我包含了我的FileUploadOptions()

 chunkedMode: false fileKey: "file" fileName: "VID_20160921_125152.mp4" headers: Object Content-Type: "video/mp4" x-amz-acl: "public-read" __proto__: Object httpMethod: "PUT" mimeType: "video/mp4" params: null 

更新2

直接使用$cordovaFileTransfer$cordovaFileTransfer插件,我得到另一个错误:

 "<?xml version="1.0" encoding="UTF-8"?> <Error><Code>AuthorizationQueryParametersError</Code><Message>Error parsing the X-Amz-Credential parameter; the Credential is mal-formed; expecting "&lt;YOUR-AKID&gt;/YYYYMMDD/REGION/SERVICE/aws4_request".</Message><RequestId>C863350E96804F5C</RequestId><HostId>7TmXBDlsGNvDmLFKgLePTMAg+Onf8y1ZPTEWmbdHPAyWHFIdt1+5J7U3H8Ygnf3sebMRpRNdxXA=</HostId></Error>" 

更新3

为了尽可能地澄清一切,我已经部署了一个github ,其中包含我正在工作的所有后端/前端。

再次感谢。

更新4

感谢daserge的帮助,我可以得到我的PUT的标题。 以下是我粘贴的结果:

 HTTP/1.1 400 Bad Request x-amz-request-id 3F686CFD09B5C6DD x-amz-id-2 KDrmvzhnrWfLB+Tdttg88MaPVOp2LOBAhwEqiBR0XdMpaje3lRsiM6mHfjv5ULzD7GweiT9C2T0= Content-Type application/xml Date Sat, 24 Sep 2016 17:00:03 GMT Server AmazonS3 Transfer-Encoding chunked Proxy-Connection Close PUT /my_bucket/uploads/VID_20160924_190000.mp4?Content-Type=video%252Fmp4&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJV3UP7LBEKPYMLGA%252F20160924%252Fus-west-2%252Fs3%252Faws4_request&X-Amz-Date=20160924T170002Z&X-Amz-Expires=600&X-Amz-Signature=ca3c992290bdf51e14bab6d67e4c520b280368bdd2a0274b552dc3e975f55c9d&X-Amz-SignedHeaders=host%253Bx-amz-acl&x-amz-acl=public-read HTTP/1.1 Content-Type application/octet-stream Content-Length 56116 User-Agent Dalvik/2.1.0 (Linux; U; Android 5.0; Aquaris E5 HD Build/LRX21M) Host s3-us-west-2.amazonaws.com Connection Keep-Alive Accept-Encoding gzip 

然后我意识到有2个参数错了:

 Content-Type: application/xml Transfer-Encoding: chunked 

而且,我已经了解了编码。 它应该是%2F ,它就像%252F

这很奇怪,因为我使用这些参数的方式似乎是正确的:

 options = { fileKey: 'file', fileName: name, chunkedMode: false, httpMethod: 'PUT', mimeType: "application/octet-stream", headers: { "Content-Type": "application/octet-stream" } }; $cordovaFileTransfer.upload(server, filePath, options) .then(function (result) { console.log(result); }, function (err) { console.log(err); }, function (progress) { console.log(progress); }); 

还有,谢谢bvakiti,我已经看到了一个错误消息,因为我正在发送video到https 。 我正在尝试http

看起来,从AWS获得的端点和使用$cordovaFileTransfer的方式之间存在冲突。

当您在服务器中使用s3.getSignedUrl获取端点时,只有响应URL的参数被编码(基本URL保持未编码)。

当你使用$cordovaFileTransfer这个函数再次编码params,这就是为什么你看到%252F匹配//

有3个选项:

  • 相反,在你的$cordovaFileTransfer调用之前,解码params

     var host = server.split('?')[0] + '?' + decodeURIComponent(server.split('?')[1]); 
  • 按照文档中的描述使用options.params

其他帮助评论中提示的encodeURI: false选项对我无效

希望能帮助到你。

我想在AWS中推导Access Key存在一些问题。

尝试使用这个:

 function getSignatureKey(key, dateStamp, regionName, serviceName) { var kDate= Crypto.HMAC(Crypto.SHA256, dateStamp, "AWS4" + key, { asBytes: true}) var kRegion= Crypto.HMAC(Crypto.SHA256, regionName, kDate, { asBytes: true }); var kService=Crypto.HMAC(Crypto.SHA256, serviceName, kRegion, { asBytes: true }); var kSigning= Crypto.HMAC(Crypto.SHA256, "aws4_request", kService, { asBytes: true }); return kSigning; } 

http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-jscript

我也发现了一个老博客,如果有帮助:

http://coenraets.org/blog/2013/09/how-to-upload-pictures-from-a-phonegap-app-to-amazon-s3/

可能是上传空体/空Content-Length的问题

看看这个线程: https : //github.com/aws/aws-sdk-js/issues/15

更新您的AWS存储桶configuration后,不要在创buildS3对象时传递参数。 尝试下面的代码。

  // make managed upload var upload = new AWS.S3.ManagedUpload({ params: metadata }); var s3Head = new AWS.S3(); 

修改路由/ endpoints.js。

在fileTransfer期间遇到了错误代码1的问题,并给出了html元素作为响应。

问题在于SSL连接。 尝试给服务器的urlhttp而不是https,它会正常工作。 但是当涉及到身份validation时,您将在后端进行更改。 cordovaFileTransfer没有问题。

希望这可以帮助。