【问题标题】:HttpError 400 when trying to upload pdf file on Google Cloud Storage尝试在 Google Cloud Storage 上上传 pdf 文件时出现 HttpError 400
【发布时间】:2016-08-23 06:26:30
【问题描述】:

我正在设置一个服务:

  1. 收到带有附件文件的电子邮件
  2. 将此文件上传到云存储
  3. 将该文件用作进一步处理的源

我到达了发生错误的第 2 步。我正在使用 Google 服务的发现 API 进行身份验证。我的是一个简单的烧瓶应用程序,下面是传入的电子邮件处理程序。

handle_incoming_email.py

__author__ = 'ciacicode'

import logging
import webapp2
from google.appengine.ext.webapp.mail_handlers import InboundMailHandler
from oauth2client.client import GoogleCredentials
from googleapiclient.discovery import build

credentials = GoogleCredentials.get_application_default()


class LogSenderHandler(InboundMailHandler):
    def receive(self, mail_message):
        logging.info("Received a message from: " + mail_message.sender)
        # upload attachment to cloud storage
        filename = 'any'
        try:
            attachment = mail_message.attachments
            filename = attachment[0].filename
            body = str(attachment[0].payload)
        except IndexError:
            print len(attachment)

        storage = build('storage', 'v1', credentials=credentials)
        req = storage.objects().insert(bucket='ocadopdf', body={'body': body, 'contentType': 'application/pdf', 'name': str(filename), 'contentEncoding': 'base64'})
        resp = req.execute()
        return resp


app = webapp2.WSGIApplication([LogSenderHandler.mapping()], debug=True)

向服务发送电子邮件后,我在日志中看到以下错误:

HttpError: https://www.googleapis.com/storage/v1/b/ocadopdf/o?alt=json 返回 "上传请求必须包含一个 uploadType URL 参数和一个 URL 以 /upload/">

开头的路径

我知道信息没有发布到正确的端点并且缺少 URL 参数,但是我在 Google 文档中挖掘的越多,我就越无法找到关于如何使用发现模块中的 .build在服务“存储”之前添加 URL 路径。

-- 更新解决方案--

    file = cStringIO.StringIO()
    file.write(body)
    media = http.MediaIoBaseUpload(file, mimetype='application/pdf')
    storage = build('storage', 'v1', credentials=credentials)
    req = storage.objects().insert(bucket='ocadopdf', body={'name': str(filename), 'contentEncoding': 'base64'}, media_body=media)
    resp = req.execute()
    return resp`

【问题讨论】:

    标签: python google-app-engine flask google-cloud-storage google-cloud-platform


    【解决方案1】:

    您的构建调用在我看来是正确的。这个example 提供了关于如何将文件作为新对象上传到 GCS 的很好的参考。除了将文件句柄传递给 MediaIoBaseUpload,您还可以传递包含对象内容的 io.BytesIO,如MediaIoBaseUpload 文档中所述

    【讨论】:

    • 嗨 Angus,不幸的是,这个例子只展示了如何在本地机器上处理文件。电子邮件附件是 google 对象,而不是常规的 python 文件对象。到目前为止,问题不在于正文的内容,而在于端点调用本身。
    • 正确 - 第二个链接显示了 MediaIoUpload 与 io.BytesIO 和任意字节的用法,但也可以是 StringIO 等。
    • 感谢@Angus Davis,即使上传后我无法成功打开 pdf,我也可以使用上面发布的更改。我认为虽然这与编码有关,但这个问题本身就得到了回答。当出现这样的错误 400 时,它表明缺少填充了正确文件流对象的 media_body 参数。
    猜你喜欢
    • 1970-01-01
    • 2019-10-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    相关资源
    最近更新 更多