I am trying to upload a file to Google Cloud Storage through an AngularJS App.
I want to use a Signed URL (so GCS Authentication details are not stored within the client side AngularJS App).
NodeJS Server Side
The follow code does return a Signed URL from GCS to the client.
var gcloud = require('google-cloud');
var storage = gcloud.storage;
var gcs = storage({
projectId: 'Google Cloud Project ID',
keyFilename: __dirname + '/Google Cloud Project Keys.json'
});
var bucket = gcs.bucket('Google Cloud Bucket Name');
router.get('/uploadurl', function(req, res) {
var file = bucket.file('test.jpg');
var config = {
action: 'write',
expires: '03-17-2025',
cname: 'Google Cloud Bucket CName'
};
file.getSignedUrl(config, function(err, url) {
if (err) {
deferred.resolve(err);
} else {
deferred.resolve(url);
}
});
})
AngularJS Client Side
Client Side, using the Signed URL (uploadURL) I try to upload to GCS.
angular.module('admin').controller('appendProjectCtrl', function($scope, $http, Upload){
$scope.$watch('projectImages', function () {
$scope.upload($scope.projectImages, "projectImages");
});
$scope.$watch('file', function () {
if ($scope.file != null) {
$scope.files = [$scope.file];
}
});
$scope.upload = function (files, uploadType) {
console.log("files: ", files);
if (files && files.length) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
if (!file.$error) {
$http.get('/api/storage/uploadurl')
.success(function(result) {
var uploadURL = result;
Upload.upload({
url: uploadURL,
file: file
}).then(function (resp) {
console.log("image upload: ", resp);
}, null, function (evt) {
console.log("evt: ", evt);
var progressPercentage = parseInt(100.0 *
evt.loaded / evt.total);
console.log(progressPercentage);
$scope.log = 'progress: ' + progressPercentage +
'% ' + evt.config.file.name + '\n' +
$scope.log;
});
})
}
}
}
};
});
However the following error is returned:
<?xml version='1.0' encoding='UTF-8'?>
<Error>
<Code>InvalidAuthentication</Code>
<Message>The provided authentication header is invalid.</Message
<Details>Cannot use Query String params with form POST.</Details>
</Error>
I understand from utilising Signed URLs in S3 (and others) that I should not need any further Authentication for the client other than pushing the file to the URL within the allocated timeframe.
I have checked CORS on Google Cloud Storage, and there does not appear to be an issue there either.
[{
"maxAgeSeconds": 3600,
"method": ["GET", "HEAD", "POST", "DELETE", "PUT"],
"origin": ["https://regulardomain.com", "http://localhost:8199"],
"responseHeader": ["*"]
}]
Any thoughts??