如何为动态生成的Google云端存储对象获取有效的blob存储密钥?

时间:2015-02-18 17:31:59

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

我有一个用例,我需要动态生成一个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模型中,我会收到类似“预期的BlobKey,得到AMIfv-yadda-yadda-yadda”的错误。

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

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

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

所以我想我的问题是,在世界上我如何获得我在Google云存储中动态生成的文件的有效密钥?

BTW:通过上传操作获取密钥很简单,但由于某种原因,动态生成的GCS对象不会产生相同的结果。

提前致谢

2 个答案:

答案 0 :(得分: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设置为私有,也可以使用。

答案 1 :(得分:0)

确定在阅读this post并修改Kekito的例子之后终于弄明白了。

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

我所要做的就是在返回文件之前将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"  
相关问题