如此处所述https://cloud.google.com/storage/docs/xml-api/post-object

从浏览器(使用签名请求)将文件上传到 GCS 时,我可以使用${filename}作为密钥的一部分。

这很好,因为它与 S3 使用的变量完全相同。 但是 - 一个问题。 当我上传时,它实际上并没有用${filename}替换${filename} 这在 S3 上非常有效,但是使用 GCS 我确实得到$%7Bfilename%7D作为响应中的键 - 显然它没有用正确的值替换它。

我正在像这样构建请求:

export function uploadVideo(video) {
  return new Promise((resolve, reject) => {
    if (!video) {
      resolve(null);
      return;
    }
    // this fetches a presigned post object from the server:
    request.get('/presigned_post')
      .query({format: 'json'})
      .end((err, response)=> {
        if (!err && response.ok) {
          request
            .post(`https://${response.body.url.host}/`)
            .field(response.body.fields)
            .field('Content-Type', image.type)
            .attach('file', image, image.name)
            .end((err, response) => {
              if (err) {
                console.log("Error uploading image: ", err);
                reject(err);
              } else {
                resolve({
                  location: response.text.match('<Location>' + '(.*?)' + '</Location>')[1],
                  bucket: response.text.match('<Bucket>' + '(.*?)' + '</Bucket>')[1],
                  key: response.text.match('<Key>' + '(.*?)' + '</Key>')[1],
                  checksum: response.text.match('<ETag>"' + '(.*?)' + '"</ETag>')[1]
                });
              }
            });
        }
      });
  });
}

键是some_folder/${filename} ,它包含在谷歌的表单数据中(在response.fields )。

你可以看到提供与文件名.attach('file', image, image.name) 正在正确上传,只是没有替换${filename}变量。

编辑

我已经进一步缩小了问题的范围。 我们查询 S3 和 GCS 以获取预签名帖子中的字段。 使用 S3,如果我给出${filename}的键,那么我会得到字段中返回的值:

  def presigned_post(bucket_name:, key:, **opts)
    response = s3_resource.
      bucket(bucket_name).
      presigned_post(key: key, content_type_starts_with: '', **opts)

    {
      fields: response.fields,
      url:    { host: URI.parse(response.url).host }
    }
  end

此处的字段将包含"key"=>"${filename}"

但是,在 GCS 情况下,以下代码在字段中返回:key=>"$%7Bfilename%7D"

# https://cloud.google.com/storage/docs/xml-api/post-object#usage_and_examples
# https://www.rubydoc.info/gems/google-cloud-storage/1.0.1/Google/Cloud/Storage/Bucket:post_object
def presigned_post(bucket_name:, key:, acl:, success_action_status:, expiration: nil)
  expiration ||= (Time.now + 1.hour).iso8601

  policy = {
    expiration: expiration,
    conditions: [
      ["starts-with", "$key", "" ],
      ["starts-with", "$Content-Type", "" ],
      { acl: acl },
      { success_action_status: success_action_status }
    ]
  }

  post_obj = get_bucket!(bucket_name).post_object(key, policy: policy)

  url_obj = { host: URI.parse(post_obj.url).host }

  # Have to manually merge in these fields
  fields = post_obj.fields.merge(
    acl: acl,
    success_action_status: success_action_status
  )

  return { fields: fields, url: url_obj }
end

如果我手动更改 GCS 请求字段中的密钥,则它可以工作。 这真的是我应该做的吗?

#1楼 票数:1 已采纳

已在google-cloud-storage v1.24.0 中发布了针对此问题的修复程序。

#2楼 票数:0

发现问题是由以下原因引起的:

      def ext_path
        URI.escape "/#{@bucket}/#{@path}"
      end

在 google-cloud-ruby-gem 的lib/google/cloud/storage/file.rb中。

这由同一文件中的def post_object调用。

我将在他们的 Github 页面上提出一个问题

  ask by max pleaner translate from so

未解决问题?本站智能推荐:

1回复

内存高效地将大文件从S3传输到Google云端存储

我在下面有一些工作代码将文件从S3传输到Google云端存储(GCS)。 根据我的理解,这会在上传到GCS之前将文件下载到内存中。 我想找到一种更有效的方法(在代码中)。 我意识到谷歌有一个转移服务,有CLI选项,但那些不适合我正在做的事情。 在我的应用程序中,下面的代码驻留在小方法
1回复

禁止的“对象”……处于活动的临时保留状态下,无法删除、覆盖或存档,直到移除保留状态

我在谷歌云存储上上传了一些对象,我收到错误消息为Forbidden Object Google::Cloud::PermissionDeniedError 。 此外,由于我正在从事大学课程项目,因此我没有 Cloud Storage 的全部权利。 你能告诉我如何删除对象吗? 我是使用 Google
2回复

gsutil 有效。 需要让 google.cloud.storage 工作

这是我想以编程方式解决的一个精确问题(例如,不是在浏览器中手动执行某些操作)。 该机器已安装 Google Cloud SDK。 gsutil ls命令成功运行 但是python3 -c "from google.cloud import storage; storage.Client().l
2回复

ReferenceError:导入@ google-cloud / storage时分配的左侧无效

当我在nodejs中导入@ google-cloud / storage时,我收到错误, 当我评论这条线时,一切正常。 以下是我得到的错误: /home/trd/TRD/new-rapi/copy/676cb539092d21127ded33478d1073ab6886fc3
2回复

找不到模块:无法解析@google-cloud/storage 上的“fs”

Module not found: Can't resolve 'fs'尝试从 GCP 存储中列出存储桶时, Module not found: Can't resolve 'fs'错误。 import { Storage } from '@google-cloud/storage'; cons
1回复

使用 Google.Cloud.Storage 进行用户身份验证

我正在用 C# 编写一个应用程序,它可以在 PC 上运行并允许用户登录 GCP 并在那里管理文件。 我查看了https://cloud.google.com/storage/docs/reference/libraries上的示例代码 文档显示了如何使用服务帐户进行身份验证,但我想使用用户身份验证
1回复

不使用JSON文件验证Google-Cloud-Storage

我正在使用.Net API并通过环境变量GOOGLE_APPLICATION_CREDENTIALS设置服务帐户JSON文件的路径进行身份验证。 但是我想做的是通过在代码中具体指定凭据属性来进行身份验证(就像我对AWS及其ID和KEY所做的那样)。 为什么? 在我的用例中,我不想让js
1回复

如何通过composer安装google \\ appengine \\ api \\ cloud_storage \\ CloudStorageTools?

我正试图弄清楚如何让我的用户在我的Google App Engine应用中上传文件。 我按照此处的说明操作: https : //cloud.google.com/appengine/docs/standard/php/googlestorage/user_upload 它始于: