使用预签名url对Amazon S3存储桶的PUT请求返回403

时间:2015-08-18 23:17:02

标签: angularjs node.js amazon-s3

我使用aws-sdk从Node.js服务器获取预签名网址。这是服务器代码,它始终返回200代码和url:

getSignedUrl: function(req, res, next){

    aws.config.update({ accessKeyId: AWS_ACCESS_KEY, secretAccessKey: AWS_SECRET_KEY });
    var s3 = new aws.S3();
    var s3_params = {
        Bucket: S3_BUCKET,
        Key: req.query.file_name,
        ContentType: req.query.file_type,
        ACL: 'public-read'
    };
    s3.getSignedUrl('putObject', s3_params, function(err, data){
        if (err) {
            return next(err);
        }
        else {
            var return_data = {
                signed_request: data,
                url: 'https://'+S3_BUCKET+'.s3.amazonaws.com/'+req.query.file_name
            };
            res.json(return_data);
        }
    });
}

我的客户端是Angular。我使用文件阅读器服务卸载了一个文件:

.factory('fileReaderFactory', ['$q', '$log', function($q, $log){

    ....

    var getReader = function(deferred, scope) {
        var reader = new FileReader();
        ....
        return reader;
    };

    var readAsDataURL = function (file, scope) {
        var deferred = $q.defer();

        var reader = getReader(deferred, scope);    

        scope.$broadcast("fileData", {
            name: file.name,
            type: file.type
        });

        reader.readAsDataURL(file);

        return deferred.promise;
    };


    return {
        readAsDataUrl: readAsDataURL
    };

}]);

我的控制器:

.controller('UploadCtrl', ['apiFactory','fileReaderFactory','$scope', function(apiFactory, fileReaderFactory, $scope){

    $scope.data = {};
    $scope.fileData = {};

    ...

    $scope.readFile = function() {
        fileReaderFactory.readAsDataUrl($scope.file, $scope)
            .then(function(result){
                $scope.imgSrc = result;
                imgUploaded = true;
            });
    };

    $scope.upload = function(){
        apiFactory.getSignedUrl($scope.fileData)
            .then(function(result){
                return apiFactory.uploadS3(result, $scope.fileData, $scope.imgSrc);
            })
            .then(function(result){
            }, function(error){
                console.log(error);
            })
    };

   ....

}]);

最后是来自apiFactory的代码片段:

apiFactory.getSignedUrl = function(data){

    return $http({
        method: 'GET',
        url: API_URL + '/sign_s3',
        params : {
            "file_name": data.name,
            "file_type": data.type,
        }
    });
};

apiFactory.uploadS3 = function(result, data, file){

    return $http({
        method: 'PUT',
        url: result.data.signed_request,
        data: file,
        headers: {
            "x-amz-acl": "public-read"
        }
    });
}

但是,当我尝试使用签名的网址上传文件时,我总是从亚马逊获得403: Forbidden

0 个答案:

没有答案