【问题标题】:How to Use Python to Send a Multipart PDF Request to OneNote如何使用 Python 向 OneNote 发送多部分 PDF 请求
【发布时间】:2016-07-03 04:39:40
【问题描述】:

我正在尝试使用 Python 将 PDF 上传到 OneNote。根据 OneNote API,我需要发布这样的请求:

Content-Type:multipart/form-data; boundary=MyAppPartBoundary
Authorization:bearer tokenString

--MyAppPartBoundary
Content-Disposition:form-data; name="Presentation"
Content-type:text/html

<!DOCTYPE html>
<html>
  <head>
    <title>A page with an embedded and displayed PDF file</title>
  </head>
    <body>
      <p>Attached is the lease agreement for the expanded offices!</p>
      <object 
        data-attachment="OfficeLease.pdf" 
        data="name:OfficeLeasePartName" 
        type="application/pdf" />
      <p>Here's the contents of our new lease.</p>
      <img data-render-src="name:OfficeLeasePartName" width="900"/>
    </body>
</html>

--MyAppPartBoundary
Content-Disposition:form-data; name="OfficeLeasePartName"
Content-type:application/pdf

... PDF binary data ...

--MyAppPartBoundary--

但是,我不知道如何在 Python 中执行多部分请求。我可以做一个基本的 text/html 请求就好了:

url = ROOT_URL+"pages"

headers = {"Content-Type":"text/html",
           "Authorization" : "bearer " + access_token}

# Format html (title & text)

html = "<html><head><title>" + title + "</title></head>"
html += "<body><p>" + text + "</p></body></html>"

# Send request

session = requests.Session()
request = requests.Request(method="POST", headers=headers,
                           url=url,  data=html)
prepped = request.prepare()
response = session.send(prepped)

我将如何为多部分修改该 Python 代码?

[########### 更新############]

根据 jayongg 的建议,我尝试了以下方法。当我这样做时,我得到的错误从“页面创建请求要求内容是多部分的,带有演示部分”切换到“多部分有效负载格式错误”。我认为这是因为我实际上并没有将 pdf 文件附加到某处?我也不确定 OneNote api 示例中的 OfficeLease.pdf 和 OfficeLeasePartName 之间有什么区别。

这是我当前的代码:

url = ROOT_URL+"pages"

path = os.path.join(pdfFolder, pdfName + ".pdf")   

headers = {"Content-Type":"multipart/form-data; boundary=MyAppPartBoundary",
           "Authorization" : "bearer " + access_token}

f = open(path, "rb").read()

txt = """--MyAppPartBoundary
        Content-Disposition:form-data; name="Presentation"
        Content-type:text/html

        <!DOCTYPE html>
        <html>
          <head>
            <title>A page with an embedded and displayed PDF file</title>
          </head>
            <body>
              <p>Attached is the lease agreement for the expanded offices!</p>
              <object 
                data-attachment="Sample5.pdf" 
                data="name:Sample5" 
                type="application/pdf" />
              <p>Here's the contents of our new lease.</p>
              <img data-render-src="name:Sample5" width="900"/>
            </body>
        </html>

        --MyAppPartBoundary
        Content-Disposition:form-data; name="OfficeLeasePartName"
        Content-type:application/pdf
        """ + f + """
        --MyAppPartBoundary--"""

session = requests.Session()
request = requests.Request(method="POST", headers=headers,
                           url=url,  data=txt)
prepped = request.prepare()
response = session.send(prepped)

[##########更新2##############]

如果我使代码更简单,它仍然会导致格式错误:

headers = {"Content-Type":"multipart/form-data; boundary=MyAppPartBoundary",
           "Authorization" : "bearer " + access_token}

txt = """--MyAppPartBoundary
        Content-Disposition:form-data; name="Presentation"
        Content-type:text/html

        <!DOCTYPE html>
        <html>
          <head>
            <title>One Note Text</title>
          </head>
            <body>
              <p>Hello OneNote World</p>
            </body>
        </html>

        --MyAppPartBoundary--
        """

session = requests.Session()
request = requests.Request(method="POST", headers=headers,
                           url=url,  data=txt)

我也试过这样。一样的:

headers = {"Content-Type":"multipart/form-data; boundary=MyAppPartBoundary",
           "Authorization" : "bearer " + access_token} 

txt = """<!DOCTYPE html>
        <html>
          <head>
            <title>One Note Text</title>
          </head>
            <body>
              <p>Hello OneNote World</p>
            </body>
        </html>"""    

files = {'file1': ('Presentation', txt, 'text/html')}

session = requests.Session()
request = requests.Request(method="POST", headers=headers,
                           url=url,  files=files)
prepped = request.prepare()
response = session.send(prepped)

【问题讨论】:

  • 尝试在最后一个--MyAppPartBoundary--之后添加一个换行符--
  • @jayongg 我做了,但它仍然给出同样的错误。即使我使代码更简单,它也会给出格式错误的错误(参见上面的 update2)。

标签: python http request multipart onenote


【解决方案1】:

事实证明,Python 将空行编码为“\n”,但 OneNote 需要“\r\n”。它还需要在最终边界之后有一个空行(“\r\n”)。最后,对于 Content-Type 和 Content-Disposition 行,正文中不能有任何前导空格(无缩进)。 (每个 Content-Disposition 行之后也应该有一个空行。)

例如,如果这是主体:

"""--MyBoundary
Content-Type: text/html
Content-Disposition: form-data; name="Presentation"

Some random text
--MyBoundary
Content-Type: text/text
Content-Disposition: form-data; name="more"; filename="more.txt"

More text
--MyBoundary--
"""

应该用字符串来表示

'--MyBoundary\r\nContent-Type: text/html\r\nContent-Disposition: form-data; name="Presentation"\r\n\r\nSome random text\r\n--MyBoundary\r\nContent-Type: text/text\r\nContent-Disposition: form-data; name="more"; filename="more.txt"\r\n\r\nMore text\r\n--MyBoundary--\r\n' 

只需在三个 """ 引号内键入文本即可完成(这将自动在最终字符串中任何有空行的地方创建 \n),然后将 "\n" 替换为 "\r\n" :

body = body.replace("\n", "\r\n")

标题是:

headers = {"Content-Type":"multipart/form-data; boundary=MyBoundary",
           "Authorization" : "bearer " + access_token} 

最后,你会像这样发布调用:

session = requests.Session()
request = requests.Request(method="POST", headers=headers,
                           url=url,  data=body)
prepped = request.prepare()
response = session.send(prepped)

【讨论】:

  • 很高兴它解决了。所以我想这也解决了,对吧? stackoverflow.com/questions/36069553/…
  • 顺便说一句,“\r\n”是 HTTP 标准的一部分。
  • 是的 :) 我将它们发布为不同的问题,因为一个只是一般情况下如何格式化 multipost,而另一个是特定于错误的。然而,解决方案回答了他们两个问题。谢谢你,这是我第一次探索 HTTP 标准,我想我错过了关于“\r\n”的部分!非常感谢您的帮助。
【解决方案2】:

您需要构建完整的 HTTP 请求,而不仅仅是发送 HTML。

对于您的身体,请尝试按照您在问题中发布的那样构建整个身体。

--MyAppPartBoundary
Content-Disposition:form-data; name="Presentation"
Content-type:text/html

<!DOCTYPE html>
<html>
  // truncated
</html>

--MyAppPartBoundary
Content-Disposition:form-data; name="OfficeLeasePartName"
Content-type:application/pdf

... PDF binary data ...

--MyAppPartBoundary--

确保正确设置内容类型标头:

Content-Type:multipart/form-data; boundary=MyAppPartBoundary

【讨论】:

  • 谢谢,我尝试了你的建议,现在它给出的错误是“多部分有效负载格式错误”而不是“页面创建请求要求内容是多部分的,带有演示部分。”你能看看我更新的例子,看看我哪里还有错吗?
猜你喜欢
  • 2020-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多