如何通过 Google App Engine 上的 URL 将文件存储在 Google Storage 上?

发布于 2024-09-30 14:45:20 字数 2603 浏览 3 评论 0原文

我想在 Google App Engine (Python) 上创建一项服务,该服务将接收图像的 URL 并将其存储在 Google Storage 上。我设法使用 botogsutil 命令行从本地文件上传,但不是通过 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

伤痕我心 2024-10-07 14:45:20

您是否阅读过有关如何签署请求的文档?除了自定义标头和资源路径之外,要签名的字符串还必须包含 Content-MD5Content-TypeDate 标头。

Have you read the docs on how to sign requests? The string to sign must include the Content-MD5, Content-Type and Date headers, in addition to the custom headers and the resource path.

寄与心 2024-10-07 14:45:20

对于 PUT,Content-MD5 标头是可选的请求。尝试将其保留进行测试。

此外,必需的标头为 AuthorizationDateHost。您的请求似乎缺少 Host 标头。

Content-MD5 header is optional for PUT requests. Try leaving this out for a test.

Also, required headers are Authorization, Date and Host. It seems that your request is missing Host header.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文