2016-03-17 2 views
1

Я пытаюсь загрузить PDF в OneNote с помощью Python. Согласно 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 где-нибудь? Я также не уверен, в чем разница между OfficeLease.pdf в примере OneNote api и 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

Try добавление новой строки после последней --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:multipart/form-data; boundary=MyAppPartBoundary 
+0

Спасибо, я попробовал ваше предложение, и теперь ошибка, которую он дает, - «Полезная нагрузка для нескольких частей была искажена», а не «Запросы на создание страницы требуют, чтобы контент был многокомпонентным, с частью презентации». Можете ли вы посмотреть мой обновленный пример и посмотреть, где я все еще ошибаюсь? – Elliptica

2

Ответ оказывается, является то, что Python кодирует пустые строки как «\ п», но OneNote требует «\ г \ п» , Для окончательной границы также требуется пустая строка («\ 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»:

заголовки будут:

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

Наконец, вы POST вызов, как это:

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

Смежные вопросы