App Engine - 从云存储下载文件

App Engine - download files from Cloud Storage

我正在使用 Python 2.7 和 Reportlab 在我的应用引擎系统中为 display/print 创建 .pdf 文件。如果重要的话,我正在使用 ndb.Model 来存储数据。

我可以在线为单个客户生成相当于银行对帐单的文件。那是;用户单击屏幕上的 'pdf' 按钮,然后 .pdf 语句出现在屏幕上的新选项卡中,正如它应该的那样。

我正在使用以下代码将 .pdf 文件成功保存到 Google 云存储

buffer = StringIO.StringIO()
self.p = canvas.Canvas(buffer, pagesize=portrait(A4))
self.p.setLineWidth(0.5)

try:

    # create .pdf of .csv data here

finally:
    self.p.save()
    pdfout = buffer.getvalue()
    buffer.close()

    filename = getgcsbucket() + '/InvestorStatement.pdf'  
    write_retry_params = gcs.RetryParams(backoff_factor=1.1)

    try:
        gcs_file = gcs.open(filename,
                            'w',
                            content_type='application/pdf',
                            retry_params=write_retry_params)
        gcs_file.write(pdfout)
    except:
        logging.error(traceback.format_exc())
    finally:
        gcs_file.close()

我正在使用以下代码创建所有文件的列表以在屏幕上显示,它显示上面存储的所有文件。

allfiles = []

bucket_name = getgcsbucket()

rfiles = gcs.listbucket(bucket_name)
for rfile in rfiles:
    allfiles.append(rfile.filename)

return allfiles

我的屏幕 (html) 显示行([删除] 和文件名)。当用户点击 [Delete] 按钮时,以下删除代码片段起作用(文件名是 /bucket/filename,完成)

filename = self.request.get('filename')
try:
    gcs.delete(filename)
except gcs.NotFoundError:
    pass

我的问题 - 鉴于我在屏幕上有一个文件列表,我希望用户单击文件名并将该文件下载到用户的计算机上。在 Google 的 Chrome 浏览器中,这将导致文件被下载,其名称显示在屏幕的左下方。

还有一点,上面的例子是针对.pdf文件的。我还必须在列表中显示 .csv 文件,并希望它们也被下载。我只想下载文件,不需要显示

所以,我想要一个片段,例如...

filename = self.request.get('filename')
try:
    gcs.downloadtousercomputer(filename) ???
except gcs.NotFoundError:
    pass

我想我已经尝试了在这里和其他地方可以找到的所有方法。对不起,我一直啰嗦。对我有什么提示吗?

要下载文件而不是在浏览器中显示它,您需要在响应中添加 header:

self.response.headers["Content-Disposition"] = 'attachment; filename="%s"' % filename

您可以如上所示指定文件名,它适用于任何文件类型。

您可以尝试的一种解决方案是从存储桶中读取文件并使用正确的 header:

将内容打印为响应
import cloudstorage
...
def read_file(self, filename):        
    bucket_name = "/your_bucket_name"        
    file = bucket_name + '/' + filename        
    with cloudstorage.open(file) as cloudstorage_file: 
        self.response.headers["Content-Disposition"] = str('attachment;filename=' + filename)            
        contents = cloudstorage_file.read()         
        cloudstorage_file.close()            
        self.response.write(contents)

此处的文件名可以是您作为 GET 参数发送的内容,并且需要是存储桶中存在的文件,否则您将引发异常。

[1] 在这里你会找到一个例子。

[1]https://cloud.google.com/appengine/docs/standard/python/googlecloudstorageclient/read-write-to-cloud-storage