来自 Google Cloud Storage 的 NodeJS getSignedUrl - 用于通过 AngularJS 客户端上传(写入)

use*_*483 5 google-app-engine node.js google-cloud-storage angularjs ng-file-upload

我正在尝试通过 AngularJS 应用程序将文件上传到 Google Cloud Storage。

我想使用签名 URL(因此 GCS 身份验证详细信息不会存储在客户端 AngularJS 应用程序中)。

NodeJS 服务器端

以下代码确实将签名 URL 从 GCS 返回给客户端。

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);
    }
  });

})
Run Code Online (Sandbox Code Playgroud)

AngularJS 客户端

客户端,使用签名 URL (uploadURL),我尝试上传到 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;
                  });

                })
            }
          }
        }
      };
});
Run Code Online (Sandbox Code Playgroud)

但是返回以下错误:

<?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>
Run Code Online (Sandbox Code Playgroud)

通过在 S3(和其他)中使用签名 URL,我了解到除了在分配的时间范围内将文件推送到 URL 之外,我不需要对客户端进行任何进一步的身份验证。

我检查了 Google Cloud Storage 上的 CORS,似乎也没有问题。

[{
   "maxAgeSeconds": 3600, 
   "method": ["GET", "HEAD", "POST", "DELETE", "PUT"], 
   "origin": ["https://regulardomain.com", "http://localhost:8199"],
   "responseHeader": ["*"]
}]
Run Code Online (Sandbox Code Playgroud)

有什么想法吗??