我试图使用Google云存储(GCS)、Python2.7和Ferris框架创建一个文档管理系统。我能够将许多类型的文件上传到云存储中,并且能够以编程方式将CSV和TXT推送到客户端浏览器下载,没有任何问题。但是,如果该文件是Microsoft Word文档、PDF或任何其他MIME类型,我会不断得到以下错误:
'ascii' codec can't decode byte 0xe2 in position X
@route
def test_get_csv_file(self):
# the file in google cloud storage
thefilename = '/mydomain.appspot.com/my_csv_file.csv'
try:
with gcs.open(thefilename, "r") as the_file:
self.response.headers["Content-Disposition"] = "'attachment'; filename=my_csv_file.csv"
return the_file.read(32*1024*1024).decode("utf-8")
except gcs.NotFoundError:
return "it failed"
@route
def test_get_word_file(self):
# the file in google cloud storage
thefilename = '/mydomain.appspot.com/my_word_file.doc'
try:
with gcs.open(thefilename, "r") as the_file:
self.response.headers["Content-Disposition"] = "'attachment'; filename=my_word_file.doc"
return the_file.read(32*1024*1024).decode("utf-8")
except gcs.NotFoundError:
return "it failed"
对文件的访问必须限制在域帐户,所以我不能将bucket的默认ACL设置为public-read,否则我只会使用storage.googlapis.com/yadda/yadda URL作为服务URL并使用它。我还尝试将decode值更改为Latin-1,但这只是呈现一个空白文件。我不明白为什么这与CSV文件工作,而不是其他任何东西。我很感激任何帮助。谢谢
它并不能真正解决你的问题。但另一种方法是使用签名URL。然后,这些文件将直接从云存储中提供,生成的url将在有限的时间内有效。
我使用下面的python模块。它有一些用于url签名的实用方法和类。
import datetime
import time
import urllib
from urlparse import urlparse
__author__ = 'fabio'
__all__ = ['sign', 'PolicyDocument', 'CloudStorageURLSigner']
from google.appengine.api import app_identity
from base64 import b64encode
import json
def sign(string_to_sign):
signing_key_name, signature = app_identity.sign_blob(string_to_sign)
return b64encode(signature)
class PolicyDocument:
"""Represents a policy.
Attributes:
content_type:
success_action_redirect:
key:
bucket:
expiration:
acl:
success_action_status:
"""
ACL = "acl"
SUCCESS_ACTION_REDIRECT = "success_action_redirect"
SUCCESS_ACTION_STATUS = "success_action_status"
KEY = "key"
BUCKET = "bucket"
CONTENT_TYPE = "content-type"
ACL_PUBLIC_READ = "public-read"
ACL_PROJECT_PRIVATE = "project-private"
def __init__(self, content_type=None, success_action_redirect=None, key=None, bucket=None, expiration=None,
success_action_status=201, acl=ACL_PROJECT_PRIVATE):
self.content_type = content_type
self.success_action_redirect = success_action_redirect
self.key = key
self.bucket = bucket
self.expiration = expiration
self.acl = acl
self.success_action_status = success_action_status
def as_dict(self):
conditions = [{self.ACL: self.acl},
{self.BUCKET: self.bucket},
{self.KEY: self.key},
{self.CONTENT_TYPE: self.content_type},
["starts-with", "$content-type", 'image/'],
]
# TODO investigate why its not working
if self.success_action_redirect:
conditions.append({self.SUCCESS_ACTION_REDIRECT: self.success_action_redirect})
else:
conditions.append({self.SUCCESS_ACTION_STATUS: str(self.success_action_status)})
return dict(expiration=self.expiration, conditions=conditions)
def as_json_b64encode(self):
return b64encode(self.as_json())
def as_json(self):
return json.dumps(self.as_dict())
class CloudStorageURLSigner(object):
"""Contains methods for generating signed URLs for Google Cloud Storage."""
DEFAULT_GCS_API_ENDPOINT = 'https://storage.googleapis.com'
def __init__(self, gcs_api_endpoint=None, expiration=None):
"""Creates a CloudStorageURLSigner that can be used to access signed URLs.
Args:
gcs_api_endpoint: Base URL for GCS API. Default is 'https://storage.googleapis.com'
expiration: An instance of datetime.datetime containing the time when the
signed URL should expire.
"""
self.gcs_api_endpoint = gcs_api_endpoint or self.DEFAULT_GCS_API_ENDPOINT
self.expiration = expiration or (datetime.datetime.now() +
datetime.timedelta(days=1))
self.expiration = int(time.mktime(self.expiration.timetuple()))
self.client_id_email = app_identity.get_service_account_name()
def __make_signature_string(self, verb, path, content_md5, content_type):
"""Creates the signature string for signing according to GCS docs."""
signature_string = ('{verb}\n'
'{content_md5}\n'
'{content_type}\n'
'{expiration}\n'
'{resource}')
return signature_string.format(verb=verb,
content_md5=content_md5,
content_type=content_type,
expiration=self.expiration,
resource=path)
def signed_url(self, verb, path, content_type='', content_md5=''):
"""Forms and returns the full signed URL to access GCS."""
base_url = '%s%s' % (self.gcs_api_endpoint, path)
signature_string = self.__make_signature_string(verb, path, content_md5,
content_type)
signature = urllib.quote_plus(sign(signature_string))
return "{}?GoogleAccessId={}&Expires={}&Signature={}".format(base_url, self.client_id_email,
str(self.expiration), signature)
def signed_download_url(self, url):
if self.is_stored_on_google_cloud_storage(url):
parsed_url = urlparse(url)
return self.signed_url('GET', parsed_url.path)
return url
@staticmethod
def is_stored_on_google_cloud_storage(url):
return "storage.googleapis.com" in url
问题内容: 我想创建一个应用程序,当超级用户单击链接时,用户应该获得通知或类似pdf的内容,以便他们在屏幕上访问。 用例:当教师想与他的学生共享PDF时,他应该能够通知他的学生有关可下载的pdf的信息,并且必须提供一个链接来做到这一点。 问题答案: 当您想在CakePHP中实现此功能(因此我假设它是基于Web的应用程序)时,用户必须打开“活动”页面才能接收推送消息。 值得一看前两个答案,但也只需考
我正在尝试使用谷歌云存储JSON API将图像上传到谷歌云存储桶中。文件正在上载,但没有显示任何内容。 我正在通过以下方式上载图像:- 图像1 看图片1,文件上传成功。但当我点击它查看它时,它显示如图2所示。 图像2
我需要在谷歌云存储中“作为最终用户进行身份验证”(我代表我的应用程序的最终用户访问资源)。因为我的应用程序是用C++编写的。我编译了C++谷歌云存储客户端库。但是这里它声明它需要客户端的JSON文件来创建GCS::Client对象。我找不到任何其他方法来创建带有项目id、服务电子邮件、私钥、密钥名和桶名等信息的客户端(这些信息足以在python中进行身份验证)。有没有办法在谷歌云存储C++客户端库
我目前面临的问题与谷歌云存储, 我能够下载对象上传到谷歌云存储,但当天晚些时候,我开始得到的错误,因为"这个网站无法到达" 我在c#中以编程方式创建了一个bucket,代码如下: 因此,创建存储桶的设置如下: 默认存储类别:多地区 位置:美国(美国多个地区) 公共访问:每个对象 生命周期:无 访问控制模型:存储桶策略
我想按照官方文档中提供的示例将一个文件上传到Google云存储 然而,我得到了一个错误: 线程“main”com.google.cloud.storage.StorageException中的异常:获取服务帐户的访问令牌时出错:400个错误请求{“错误”:“无效的授予”、“错误描述”:“无效的JWT:令牌必须是短期令牌(60分钟)并且在合理的时间范围内。请检查JWT声明中的iat和exp值。”位于
我有一个谷歌云,我想推我的图像。 我的图片是Hello-world项目与节点快递谷歌云客户端libray 你可以在我的github上找到它 https://github.com/innostarterkit/language 当我试着推的时候,我有这个错误 推送是指存储库[eu.gcr.io/innovation xxx/hello]a419c4413fb0:推送[================