Can';t使用带有预签名URL的Angularjs将文件上载到AmazonS3

Can';t使用带有预签名URL的Angularjs将文件上载到AmazonS3,angularjs,grails,amazon-web-services,amazon-s3,Angularjs,Grails,Amazon Web Services,Amazon S3,我在将文件上载到Amazon S3时遇到问题。我开发了一个GrailsRESTful服务,它使用AWS生成预签名URL。当客户端上传一个文件时,它首先检索一个预签名的URL,然后使用它将文件直接上传到我的S3存储桶。所以我有一个Grails服务,它创建了一个预签名的URL,就像这样 def generateFileUploadUrl(AmazonS3Client client, String bucketName, String key, int expiryMins) { Genera

我在将文件上载到Amazon S3时遇到问题。我开发了一个GrailsRESTful服务,它使用AWS生成预签名URL。当客户端上传一个文件时,它首先检索一个预签名的URL,然后使用它将文件直接上传到我的S3存储桶。所以我有一个Grails服务,它创建了一个预签名的URL,就像这样

def generateFileUploadUrl(AmazonS3Client client, String bucketName, String key, int expiryMins) {
    GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, key);
    req.setMethod(HttpMethod.POST);
    req.setExpiration(getExpiration(expiryMins)); 
    return client.generatePresignedUrl(req);
}
Upload.upload({
    url: destUrl, // url shown above
    file: file
}).progress(function (evt) {
  var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
  console.log('progress: ' + progressPercentage + '% ' + evt.config.file.name);
}).success(function (data, status, headers, config) {
  console.log('file ' + config.file.name + 'uploaded. Response: ' + data);
}).error(function (data, status, headers, config) {
  console.log('error status: ' + status);
});
然后,客户端检索具有以下格式的URL

https://{bucketname}.amazonaws.com/{key}?AWSAccessKeyId={accesskey}&Expires={expiry}&Signature={signature}
然后客户端使用Danial Farid的类似于这样的方法创建一个POST请求

def generateFileUploadUrl(AmazonS3Client client, String bucketName, String key, int expiryMins) {
    GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, key);
    req.setMethod(HttpMethod.POST);
    req.setExpiration(getExpiration(expiryMins)); 
    return client.generatePresignedUrl(req);
}
Upload.upload({
    url: destUrl, // url shown above
    file: file
}).progress(function (evt) {
  var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
  console.log('progress: ' + progressPercentage + '% ' + evt.config.file.name);
}).success(function (data, status, headers, config) {
  console.log('file ' + config.file.name + 'uploaded. Response: ' + data);
}).error(function (data, status, headers, config) {
  console.log('error status: ' + status);
});
起初,我收到关于CORS设置的错误,但在我的Bucket权限中编辑CORS源配置后,我开始收到403禁止响应。403响应中的消息是“我们计算的请求签名与您提供的签名不匹配。请检查您的密钥和签名方法。“。AWS访问密钥和提供的签名匹配,因此我不确定确切的错误是什么

我的请求是否缺少一些额外的信息?查看了其他一些帖子,比如,它手动创建了一个策略文档,并用URL发送,但它没有使用AWS Java SDK


碰巧,我的方法可以很好地处理GET请求,并且我可以检索文档。只是无法上传

我知道这是一个老问题,但它似乎仍然相关,而且要让它起作用似乎还是相当棘手的。S3签名的URL上传对于请求和响应中使用的字段非常特别,错误消息并不像您看到的那样有帮助-我认为这是出于安全原因的意图,但它确实使调试变得困难

AWS签名流程也发生了变化——此时(2016年3月)的版本为AWS签名版本4()。在查看示例和Stackoverflow等时,您需要小心,这些信息与您正在使用的同一签名版本有关,因为它们不能很好地混合

我开始使用AWS SDK进行角度/节点文件上载,但最终发现在没有SDK的情况下,在服务器(node.js)端生成策略更容易。这里有一个很好的例子(尽管是基于节点的,而不是基于Grails的):(但请注意这里的S3 bucket名称的问题:)

需要注意的一个关键问题是,在策略生成中正确地包含文件内容类型,并且该内容类型与实际上载的文件的内容类型正确匹配

作为参考,这是角度方面的代码,对我来说很有用:

$scope.upload = function (file) {
    console.log("WebUploadCtrl upload");
    console.log("WebUploadCtrl sending S3sign request");
    var query = {
        filename: file.name,
        type: file.type
    };
    $http.post('/api/s3sign', query).success(function(response) {
        console.log("WebUploadCtrl s3sign response received");
        var s3ResponseParams = response;
        console.log("WebUploadCtrl upload  AWSAccessKeyId: " + response.AWSAccessKeyId);
        console.log("WebUploadCtrl upload  signature: " + response.Signature);
        $scope.upload = Upload.upload({
                url: s3ResponseParams.url, //s3Url
                transformRequest: function(data, headersGetter) {
                    var headers = headersGetter();
                    delete headers.Authorization;
                    return data;
                },
                fields: s3ResponseParams.fields, //credentials
                method: 'POST',
                file: file
            }).progress(function(evt) {
                $scope.progressPerCent = parseInt(100.0 * evt.loaded / evt.total);
                console.log('progress: ' + $scope.progressPerCent);
            }).success(function(data, status, headers, config) {
                // file is uploaded successfully
                console.log('file ' + config.file.name + 'is uploaded successfully. Response: ' + data);                

            }).error(function() {
                // Some error has occured
                console.log('Error uploading to S3');
          });
    });
};

req.setMethod(HttpMethod.POST)。。。但是
POST
!=<代码>放
…对不起我的错。我应该说是波斯特。已经更正了帖子,谢谢。