繁体   English   中英

cordova-plugin-file-transfer:如何使用签名的URL将文件上传到S3?

[英]cordova-plugin-file-transfer: How do you upload a file to S3 using a signed URL?

我可以使用文件选择器和常规XMLHttpRequest (用于测试S3设置)将其上传到S3,但无法弄清楚如何使用cordova文件传输插件成功完成此操作。

我认为这与该插件未构造正确的可签名请求有关,或者与该给定的本地文件uri不相关。 我已经尝试过处理从标头到uri类型的每个参数,但是文档并没有太大帮助,并且插件来源是bolognese。

请求需要签名匹配的字符串如下:

PUT


1391784394
x-amz-acl:public-read
/the-app/317fdf654f9e3299f238d97d39f10fb1

有什么想法,或者可能是一个有效的代码示例?

有点晚了,但是我花了几天时间来解决这个问题,以防万一其他人遇到问题,这就是如何使用AWS开发工具包的javascript版本上载图像来创建预签名URL的方法。

解决此问题的关键是从亚马逊返回的XML SignatureDoesNotMatch错误的StringToSign元素。 就我而言,它看起来像这样:

<StringToSign>
    PUT\n\nmultipart/form-data; boundary=+++++org.apache.cordova.formBoundary\n1481366396\n/bucketName/fileName.jpg
</StringToSign>

当您使用aws-sdk生成要上传到S3的预签名URL时,它将在内部基于您要发出的请求的各种元素构建一个字符串,然后使用您的AWS密钥为其创建SHA1哈希。 此哈希是作为参数附加到URL的签名,当您收到SignatureDoesNotMatch错误时,该SignatureDoesNotMatch不匹配。

因此,您已经创建了预签名的URL,并将其传递给cordova-plugin-file-transfer以发出HTTP请求来上传文件。 当该请求到达Amazon服务器时,服务器本身将根据请求标头等构建一个字符串,对其进行哈希处理并将该哈希与URL上的签名进行比较。 如果哈希值不匹配,则返回可怕的...

The request signature we calculated does not match the signature you provided. Check your key and signing method.

我上面提到的StringToSign元素的内容是服务器构建并哈希以与预签名URL上的签名进行比较的字符串。 因此,为避免出现错误,您需要确保aws-sdk构建的字符串与服务器构建的字符串相同。

经过一番探索,我最终找到了负责创建要哈希到aws-sdk的字符串的代码。 它位于(自2.7.12版本起)位于:

node_modules/aws-sdk/lib/signers/s3.js

在第168行底部,有一个sign方法:

sign: function sign(secret, string) { return AWS.util.crypto.hmac(secret, string, 'base64', 'sha1'); }

如果在其中放置console.log ,则string是您要使用的。 一旦使传递到此方法的string与从亚马逊返回的错误消息中的StringToSign的内容相同,天堂就会打开,您的文件将毫不费力地流入您的存储桶。

在运行node.js的服务器上,我最初创建了这样的预签名URL:

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

var s3 = new AWS.S3(options = {
    endpoint: 'https://s3-eu-west-1.amazonaws.com',
    accessKeyId: "ACCESS_KEY",
    secretAccessKey: "SECRET_KEY"
});

var params = {
    Bucket: 'bucketName',
    Key: imageName,
    Expires: 60
};

var signedUrl = s3.getSignedUrl('putObject', params);

//return signedUrl

这产生了一个类似于OP的签名字符串:

PUT


1481366396
/bucketName/fileName.jpg

在客户端,我将此预签名URL与cordova-plugin-file-transfer使用(如下所示)(我正在使用Ionic 2,因此该插件被包装在其本地包装器中):

let success = (result: any) : void => { 
    console.log("upload success");
}

let failed = (err: any) : void => {
    let code = err.code;
    alert("upload error - " + code);
}

let ft = new Transfer();

var options = {
    fileName: filename,
    mimeType: 'image/jpeg',
    chunkedMode: false,
    httpMethod:'PUT',
    encodeURI: false,
};

ft.upload(localDataURI, presignedUrlFromServer, options, false)
.then((result: any) => {
    success(result);
}).catch((error: any) => {
    failed(error);
});

运行生成的代码,签名不匹配错误,并且<StringToSign>元素中的字符串如下所示:

PUT

multipart/form-data; boundary=+++++org.apache.cordova.formBoundary
1481366396
/bucketName/fileName.jpg

因此,我们可以看到cordova-plugin-file-transfer已在其自己的Content-Type标头中添加,这导致了签名字符串的差异。 在与options对象相关的文档中 ,该文档传递到upload方法中,它说:

headers: A map of header name/header values. Use an array to specify more than one value. On iOS, FireOS, and Android, if a header named Content-Type is present, multipart form data will NOT be used. (Object)

因此,基本上,如果未设置Content-Type标头,则默认为多部分表单数据。

好的,现在我们知道了问题的原因,这是一个非常简单的修复。 在服务器端,我将ContentType添加到传递给S3 getSignedUrl方法的params对象中:

var params = {
    Bucket: 'bucketName',
    Key: imageName,
    Expires: 60,
    ContentType: 'image/jpeg' // <---- content type added here
};

和客户端上添加一个headers反对options传递给cordova-plugin-file-transfer的上传方法:

var options = {
    fileName: filename,
    mimeType: 'image/jpeg',
    chunkedMode: false,
    httpMethod:'PUT',
    encodeURI: false,
    headers: { // <----- headers object added here
        'Content-Type': 'image/jpeg',
    }
};

嘿,presto! 现在可以正常进行上传。

我在这个插件中遇到了这样的问题

我发现上传带有签名的文件的唯一可行方法是Christophe Coenraets的方法: http ://coenraets.org/blog/2013/09/how-to-upload-pictures-from-a-phonegap-app- 到亚马逊-S3 /

使用此方法,您将可以使用cordova-plugin-file-transfer上载文件

首先,我想使用服务器上的aws-sdk与getSignedUrl()进行签名,它返回已签名的链接,而您只需要上传到该链接即可。

但是,使用插件时,它总是以403结尾:签名不匹配

它可能与content length参数有关,但是我暂时没有找到可使用aws-sdk和插件的解决方案

暂无
暂无

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

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