2016-03-17 119 views
1

我試圖使用Python將PDF上傳到OneNote。根據OneNote API,我需要發佈這樣的請求:如何使用Python將多部分PDF請求發送到OneNote

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中執行多部分請求。我可以做一個基本的文本/ 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代碼?

[########### UPDATE ############]

基於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) 

[########## UPDATE 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) 
+0

嘗試用最後--MyAppPartBoundary-- – jayongg

+0

@jayongg我做了後加入一個換行符,但它仍然給出同樣的錯誤。即使我使代碼更簡單,它也會給出錯誤的錯誤(參見上面的update2)。 – Elliptica

回答

0

您需要構建完整的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頭正確:

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

謝謝,我嘗試了你的建議,現在它給出的錯誤是「多部分負載格式錯誤」,而不是「頁面創建請求要求內容是多部分的,並且有一個演示文稿部分。」你能看看我更新的例子,看看我還在哪裏錯了嗎? – Elliptica

2

事實證明,答案是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,然後用「\ r \ n」替換「\ 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) 
+0

很高興它解決了。所以我認爲這也解決了,對吧? http://stackoverflow.com/questions/36069553/python-multipart-post-malformed – jayongg

+0

順便說一句,「\ r \ n」是HTTP標準的一部分。 – jayongg

+0

是的:)我發佈他們作爲不同的問題,因爲一般只是如何格式multipost,但另一個是錯誤特定的。然而,解決方案回答了他們兩個。 謝謝你,這是我第一次探索HTTP標準,我想我錯過了關於「\ r \ n」的部分!我非常感謝你的幫助。 – Elliptica

相關問題