Java 除了Android,AWS签名的URL在任何地方都可以工作

Java 除了Android,AWS签名的URL在任何地方都可以工作,java,android,amazon-web-services,aws-lambda,Java,Android,Amazon Web Services,Aws Lambda,我正在使用AWS Lambda为我的移动产品创建一个简单的上传服务 在服务器上,我使用以下代码生成一个预先签名的URL var params = { Bucket: targetS3Bucket, Key: key, Body: '', ContentType: event.contentType, Expires: 60 }; s3.getSignedUrl('putObject', params, function (err, url){ c

我正在使用AWS Lambda为我的移动产品创建一个简单的上传服务

在服务器上,我使用以下代码生成一个预先签名的URL

var params = {
    Bucket: targetS3Bucket,
    Key: key,
    Body: '',
    ContentType: event.contentType,
    Expires: 60
};

s3.getSignedUrl('putObject', params, function (err, url){
    context.done(null, {
        'oneTimeUploadUrl': url,
        'resultUrl': urlPrefix + key
    });
});
其中,
targetS3Bucket
是S3上文件夹的路径,
key
是文件本身的名称,
urlpeffix
是S3上文件的HTTP位置的根(即:
S3.amazonaws.com/some folder/

将此代码与内置HTTP库一起使用(,也就是说,不使用任何aws SDK)可以在PC和iOS上正常工作,但在Android上不会

Android客户端代码的最新版本如下所示:

uri = new URL(oneTimeUploadUrl);

// Setup Connection
HttpsURLConnection http = (HttpsURLConnection) uri.openConnection();
http.setDoOutput(true);
http.setRequestMethod("PUT");
​
// Write Data
OutputStream os = http.getOutputStream();
os.write(_bytes);
os.flush();
os.close(); // request gets sent off to the server
如果代码
400
,则此操作始终失败。我尝试过几种方法,如更改编码、使用非https版本的
HttpsURLConnection
和其他一些方法,但都没有效果

我更愿意避免引入AWS SDK,因为我只需要这一个函数就可以工作,而使用这个lambada端解决方案使得除了android之外的所有平台都可以实现这一点

这是从AWS返回的XML。返回的消息令人困惑,因为客户端从不更改令牌,并且相同的过程在其他设备上成功

<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>InvalidToken</Code>
    <Message>The provided token is malformed or otherwise invalid.</Message>
    <Token-0>{Token-0}</Token-0>
    <RequestId>{RequestId}</RequestId>
    <HostId>{HostId}</HostId>
</Error>

问题是,
HttpURLConnection
以静默方式将
内容类型:application/x-www-form-urlcoded
添加到请求中。这很烦人,因为很难确定
HttpURLConnection
对象请求中的头

无论如何。这是正确的代码

uri = new URL(oneTimeUploadUrl);

// Setup Connection
HttpsURLConnection http = (HttpsURLConnection) uri.openConnection();
http.setDoOutput(true);
http.setRequestMethod("PUT");
http.setRequestProperty("Content-Type"," "); // remove Content-Type header

// Write Data
OutputStream os = http.getOutputStream();
os.write(_bytes);
os.flush();
os.close(); // request gets sent off to the server

另请参见:

您能否捕获伴随
400错误请求的响应正文?应该有一些人类可读的XML,其中有一个提示,帮助我们弄清楚具体发生了什么。否则,这只是猜测。用这些信息更新了主要评论谢谢更新。我想,我们需要少编一些东西。预签名URL或错误响应中没有任何内容是真正敏感的——RequestId和HostId只是AWS支持用来研究日志中错误的值,因此这些值不需要显示(但不敏感),如果您想删除accesskeyid(通常以*IA开头),您可以从URL中删除它们。。。但我们可能需要查看URL的其余部分和响应。