【问题标题】:How do I get a valid blobstore key for a google cloudstorage object that is generated dynamically?如何为动态生成的谷歌云存储对象获取有效的 Blob 存储密钥?
【发布时间】:2015-04-19 19:59:00
【问题描述】:

我有一个用例,我需要动态生成一个 csv/txt 文件,然后将文件的密钥保存到数据存储区,以便以后可以下载该文件。我似乎在生成与 Ferris 的下载 uri 结合使用的有效密钥时遇到问题。 比如:

import cloudstorage
from google.appengine.ext import blobstore
@route
def make_file(self):
    # Hardcoded filename, this will overwrite prior file if it exists
    filename = '/mydomain.appspot.com/some_folder/myawesometextfile2.txt'

    # Create file 
    gcs_file = cloudstorage.open(filename,'w',content_type='text/plain')

    # Generate the file's contents (pretend this is being done dynamically)
    gcs_file.write('Doe,John\n')
    gcs_file.write('Smith,Jane\n')

    # Close the file
    gcs_file.close() 

    # This is supposed to create a blobkey that represents the cloud object
    psuedo_blobkey = blobstore.create_gs_key('/gs'+filename)

    # This is supposed to also create a blobkey...I think?
    another_key = blobstore.BlobKey(psuedo_blobkey)

    # Here I attempt to store this in the datastore.
    new_file = self.meta.Model(
                        file_key = another_key,
                        file_name_actual = filename,
                        )
    new_file.put() 

如果我尝试将“psuedo_blobkey”保存到我的 NDB 模型中,我会收到类似“Expected BlobKey, got AMIfv-yadda-yadda-yadda”的错误。

如果我尝试将“another_key”保存到我的模型中,它会毫无问题地存储密钥,但是当我尝试通过 appengine 仪表板中的数据存储查看器访问实体时,它会告诉我它不是有效的密钥。因此,当我尝试像这样在我的 jinja 模板中使用密钥时:

<a href="{{uri("download", blob=file_key)}}" target="_blank">Export</a>

Ferris 呈现错误“找不到资源”。这是有道理的,因为它显然不是有效的密钥。

所以我想我的问题是,我到底如何才能为我在谷歌云存储中动态生成的文件获取有效密钥?

顺便说一句:通过上传操作获取密钥很容易,但由于某种原因,动态生成的 GCS 对象不会产生相同的结果。

提前致谢

【问题讨论】:

  • 你能保存文件名而不是密钥吗?这就是您获取文件所需的全部内容。
  • 当然,我可以保存文件名,但我尝试使用 http://storage.googleapis.com/ / 但除非 ACL 设置为公开的,我不想这样做。即使我做了文档描述设置 acl 如下: options ={' x-goog-acl': 'public-read'} 但这甚至不起作用,谷歌会产生错误。如果你有例子,我很乐意试一试。

标签: google-app-engine python-2.7 google-cloud-storage


【解决方案1】:

我存储文件名而不是密钥。我存储的文件不是很大,所以在我的应用引擎代码中我是这样读取它们的:

def get_gcs(fn):
    "Slurps a GCS file and returns it as unicode."
    try:
        with gcs.open(fn, "r") as f:
            return f.read(32*1024*1024).decode("utf-8")
    except gcs.NotFoundError:
        return ""

然后我使用标准应用引擎技术将它们提供给用户。如果您的文件很小,这可以正常工作,但如果您的文件很大,则可能有更好的方法。

由于您是通过应用程序引擎获取文件,因此即使 ACL 设置为私有也可以使用。

【讨论】:

  • 这绝对足以提供 csv/txt 导出功能。仍然不确定如何启动下载对话框,但我不会贪心,这会做。非常感谢!!!
  • @user2744119 如果您认为以上答案回答了您的问题,您应该接受它。
  • 从技术上讲,这更像是一种解决方法。我仍然没有得到我真正需要的云存储对象的密钥。抱歉,我应该更清楚地说明这一点。
  • psuedo_blobkey 保存为模型中的字符串怎么样?
  • 如果我这样做了,我仍然会得到“找不到资源”,因为它无法将其识别为有效密钥。
【解决方案2】:

OK 在阅读this post 并修改 Kekito 的示例后终于弄明白了。

最终,我试图做的是允许最终用户从 NDB 数据存储中导出数据。我原本以为我必须生成一个文件,把它放在谷歌云存储 (GCS) 或 blobstore 中,然后提供一个下载 URL。我发现它比这简单得多。我什至认为您不需要在 GCS 中创建文件来执行此操作(即使我的示例确实将文件添加到 GCS)。

我所要做的就是在返回文件之前将 Content-Disposition 添加为附件。这会生成“另存为”对话框,允许用户确定下载位置。如果没有 content-disposition,CSV/TXT 内容会在浏览器上呈现,如果用户尝试在浏览器中保存,则唯一的选择是 HTML,并且无法更改(无论如何在 Chrome 中)。

import csv
import cloudstorage
@route
def export_users(self):
    # This can be any NDB query
    user_data = self.Meta.Model.get_users(is_active=True)

    # Set the file name 
    filename = '/mydomain.appspot.com/user_list.csv'

    # Create the file
    gcs_file = cloudstorage.open(filename,'w',content_type='text/csv')

    # Setup the CSV file for writing
    writer = csv.writer(gcs_file, delimiter=',')

    # Loop thru the query and write each row to the CSV file
    for user_info in user_data:
        writer.writerow( (str(user_info.user_lname),str(user_info.user_fname)) )

    # Close the file
    gcs_file.close()

    try:
        # Open the file for reading
        with cloudstorage.open(filename, "r") as the_file:
            # This will open the Save-As dialog box so the end-user can choose where to save the file
            self.response.headers["Content-Disposition"] = "'attachment'; filename=user_list.csv"

            # Push the file to the browser
            return the_file.read(32*1024*1024).decode("utf-8")
    except cloudstorage.NotFoundError:
        return "it failed"  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-25
    • 2018-05-11
    • 1970-01-01
    • 2013-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多