如何通过 Google App Engine 上的 URL 将文件存储在 Google Storage 上?
我想在 Google App Engine (Python) 上创建一项服务,该服务将接收图像的 URL 并将其存储在 Google Storage 上。我设法使用 boto
或 gsutil
命令行从本地文件上传,但不是通过 URL 检索文件。我尝试使用 HTTP 请求 (PUT< /code>)
并且我收到了错误签名的错误响应。显然我做错了什么,但不幸的是我不知道哪里错了。
所以我的问题是:如何使用 Python for Google App Angine 从 URL 检索文件并将其存储在 Google Storage 上?
这是我所做的(使用另一个答案< /a>):
class ImportPhoto(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
srow = self.response.out.write
url = self.request.get('url')
srow('URL: %s\n' % (url))
image_response = urlfetch.fetch(url)
m = md5.md5()
m.update(image_response.content)
hash = m.hexdigest()
time = "%s" % datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT")
str_to_sig = "PUT\n" + hash + "\n\n" +
time + "\nx-goog-acl:public-read\n/lipis/8418.png"
sig = base64.b64encode(hmac.new(
config_credentials.GS_SECRET_ACCESS_KEY,
str_to_sig, hashlib.sha1).digest())
total = len(image_response.content)
srow('Size: %d bytes\n' % (total))
header = {"Date": time,
"x-goog-acl": "public-read",
"Content-MD5": hash,
'Content-Length': total,
'Authorization': "GOOG1 %s:%s" %
(config_credentials.GS_ACCESS_KEY_ID, sig)}
conn = httplib.HTTPConnection("lipis.commondatastorage.googleapis.com")
conn.set_debuglevel(2)
conn.putrequest('PUT', "/8418.png")
for h in header:
conn.putheader(h, header[h])
conn.endheaders()
conn.send(image_response.content + '\r\n')
res = conn.getresponse()
srow('\n\n%d: %s\n' % (res.status, res.reason))
data = res.read()
srow(data)
conn.close()
我得到的答复是:
URL: https://stackoverflow.com/users/flair/8418.png
Size: 9605 bytes
400: Bad Request
<?xml version='1.0' encoding='UTF-8'?><Error><Code>BadDigest</Code><Message>The Content-MD5 you specified did not match what we received.</Message><Details>lipis/hello.jpg</Details></Error>
I want to create a service on Google App Engine (Python) that will receive a URL of an image and store it on Google Storage. I managed to upload from a local file using boto
or gsutil
command line, but not by retrieving the file via URL. I tried doing it using the HTTP requests (PUT
) and I'm getting error responses for wrong signatures. Obviously I'm doing something wrong, but unfortunately I have no idea where.
So my question is: How can I retrieve a file from a URL and store it on Google Storage using Python for Google App Angine?
Here is what I've done (using another answer):
class ImportPhoto(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
srow = self.response.out.write
url = self.request.get('url')
srow('URL: %s\n' % (url))
image_response = urlfetch.fetch(url)
m = md5.md5()
m.update(image_response.content)
hash = m.hexdigest()
time = "%s" % datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT")
str_to_sig = "PUT\n" + hash + "\n\n" +
time + "\nx-goog-acl:public-read\n/lipis/8418.png"
sig = base64.b64encode(hmac.new(
config_credentials.GS_SECRET_ACCESS_KEY,
str_to_sig, hashlib.sha1).digest())
total = len(image_response.content)
srow('Size: %d bytes\n' % (total))
header = {"Date": time,
"x-goog-acl": "public-read",
"Content-MD5": hash,
'Content-Length': total,
'Authorization': "GOOG1 %s:%s" %
(config_credentials.GS_ACCESS_KEY_ID, sig)}
conn = httplib.HTTPConnection("lipis.commondatastorage.googleapis.com")
conn.set_debuglevel(2)
conn.putrequest('PUT', "/8418.png")
for h in header:
conn.putheader(h, header[h])
conn.endheaders()
conn.send(image_response.content + '\r\n')
res = conn.getresponse()
srow('\n\n%d: %s\n' % (res.status, res.reason))
data = res.read()
srow(data)
conn.close()
And I'm getting as a response:
URL: https://stackoverflow.com/users/flair/8418.png
Size: 9605 bytes
400: Bad Request
<?xml version='1.0' encoding='UTF-8'?><Error><Code>BadDigest</Code><Message>The Content-MD5 you specified did not match what we received.</Message><Details>lipis/hello.jpg</Details></Error>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您是否阅读过有关如何签署请求的文档?除了自定义标头和资源路径之外,要签名的字符串还必须包含
Content-MD5
、Content-Type
和Date
标头。Have you read the docs on how to sign requests? The string to sign must include the
Content-MD5
,Content-Type
andDate
headers, in addition to the custom headers and the resource path.对于 PUT,
Content-MD5
标头是可选的请求。尝试将其保留进行测试。此外,必需的标头为
Authorization
、Date
和Host
。您的请求似乎缺少Host
标头。Content-MD5
header is optional for PUT requests. Try leaving this out for a test.Also, required headers are
Authorization
,Date
andHost
. It seems that your request is missingHost
header.