【问题标题】:Google App Engine: store uploaded file in Google Cloud StorageGoogle App Engine:将上传的文件存储在 Google Cloud Storage 中
【发布时间】:2015-05-06 21:00:54
【问题描述】:

我已经设法在 Google App Engine 应用程序的 webapp2 处理程序的 post 方法中在 GCS 中创建了一个文件。我看不到如何在 GCS 中创建的文件中复制已发布文件的内容。 这是我的代码

 inFile =  self.request.POST.multi['file'].file
 gcs_file = gcs.open(filename,
                    'w',
                    content_type='text/plain',
                    options={'x-goog-meta-foo': 'foo',
                             'x-goog-meta-bar': 'bar'},
                    retry_params=write_retry_params)
  while 1:
        line = inFile.readline()
        if not line: break
        gcs_file.write(line)
  gcs_file.close()

在进程结束时,GCS 中的文件为 0 字节

更新 我不使用 blobstore 是有原因的。使用 Blobstore 时,您必须创建一个 url 并将其返回给客户端。它是执行实际上传的客户端。 INSTEAD 我需要先加密服务器上的文件,然后才能将其放入 GCS。因此,我需要从客户端接收文件,在服务器上对其进行加密并将其存储在 GCS 中。

【问题讨论】:

  • 您没有一次写入整个文件有什么原因吗?另外,您是否通过logging 验证您已正确接收到具有您期望的 POST 内容长度的文件?
  • 啊,我记得你上一个问题。您似乎对上传到您的 webapp2 处理程序一无所知。停下来。你做错了。使用 BLOBSTORE。是的。您使用 blobstore 将文件获取到 GCS。您真的应该阅读整个 blobstore 概述。如果您不执行基本步骤,我不确定您是否会在这里获得任何帮助。
  • @Zachary 我已经通过验证 self.request.POST.multi['file'].filename 实际上返回了预期的字符串来检查文件是否已上传。我希望这意味着内容也已上传。我也试过 gcs_file.write(inFile.read()) 但仍然得到 0 个字节
  • @Zachary 我已验证字节已正确上传,因为上传的大小正确。但是该循环有问题,因为它只进入一次(并且 readline 返回 null)。我应该如何阅读文件内容?
  • @user2771609:“如果您不执行基本步骤,我不确定您是否会在这里获得任何帮助。”... Google 提供了此 API,因此它是有效的。即使 Sindico 并不真正需要绕过 Blobstore 并且只是想这样做,这仍然是一个足够好的解决方案(对于 GAE)。

标签: python google-app-engine webapp2


【解决方案1】:

我已使用以下方法成功地将文件 POST 到 GCS:

def post(self):
    write_retry_params = gcs.RetryParams(backoff_factor=1.1)
    filename = '/{MY-BUCKET-NAME}/static.txt'

    gcs_file = gcs.open(
        filename,
        'w',
        content_type='text/plain',
        options={'x-goog-meta-foo': 'foo',
                 'x-goog-meta-bar': 'bar'},
        retry_params=write_retry_params)

    inFile = self.request.POST.multi['file'].file
    while 1:
        line = inFile.readline()
        if not line:
            break
        gcs_file.write(line)
        logging.info('Wrote line: {}'.format(line))

    gcs_file.close()

这是来自控制台的小日志消息:

I 09:20:32.979 2015-05-07  200      84 B   1.13s /static
    76.176.106.172 - - [07/May/2015:09:20:32 -0700] "POST /static HTTP/1.1" 200 84 - "curl/7.37.1" "{MY-APP}" ms=1131 cpu_ms=1355 cpm_usd=0.000009 loading_request=1 instance=00c61b117cee89e66d34a42c5bbe3cf2b0bb06b5 app_engine_release=1.9.20
I 09:20:32.832 Wrote line: stack
I 09:20:32.833 Wrote line: overflow

这是我上传的test.txt 文件:

stack
overflow

还有我使用的 cURL 命令:

curl -F"file=@/Users/{name}/test.txt" http://{MY-APP}/videostatic

如果您仍然从 readline()read() 收到 0 个字节,我将不得不假设您的客户端未发送正确的多部分消息。

【讨论】:

  • @Sindico:不客气。我很好奇,你的解决方法是什么?
  • 我犯了一个愚蠢的错误。加密将输入文件留在 EOF 位置。
【解决方案2】:

在 Google App Engine 应用程序中将文件上传到 GCS 的推荐方法似乎是使用带有 gcs 存储桶支持的 blobstore。

https://cloud.google.com/appengine/docs/python/blobstore/#Python_Using_the_Blobstore_API_with_Google_Cloud_Storage

您不应该直接上传到 webapp2 处理程序的原因有很多。

  1. 文件大小限制。
  2. 请求持续时间的限制。
  3. 额外费用,因为您在处理程序运行时需要付费。

仅举几例......

更新

为了解决问题的更新:您仍然应该上传到 blobstore。分 3 步完成:

  1. 上传到 blobstore。
  2. 从 blobstore 读取,并将加密写入 GCS。
  3. 从 blobstore 中删除。

【讨论】:

    最近更新 更多