我有一个用例,我需要动态生成一个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对象不会产生相同的结果。
提前致谢
答案 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"