2013-04-01 7 views
8

मैं पाइथन में अनुरोधों का उपयोग करके एक मल्टीपार्ट/संबंधित संदेश भेजने की कोशिश कर रहा हूं। स्क्रिप्ट काफी सरल लगती है, सिवाय इसके कि अनुरोध केवल मल्टीपार्ट/फॉर्म-डेटा संदेशों को भेजने की अनुमति देते हैं, हालांकि उनके दस्तावेज स्पष्ट रूप से इस तरह से एक या दूसरे को नहीं बताते हैं।पायथन में अनुरोधों के साथ "मल्टीपार्ट/संबंधित" कैसे भेजें?

मेरे उपयोग के मामले अनुलग्नकों के साथ साबुन भेज रहा है। मैं दो फाइलों के साथ एक शब्दकोश प्रदान कर सकता हूं जिनकी सामग्री एक परीक्षण साबुन संदेश है, और एक परीक्षण दस्तावेज़ जिसे मैं भेजने की कोशिश कर रहा हूं। पहले सभी निर्देशों के साथ साबुन संदेश होता है, दूसरा वास्तविक दस्तावेज़ है।

हालांकि, अगर मैं एक हेडर मूल्य निर्दिष्ट नहीं करते हैं, अनुरोध केवल जब फ़ाइलें विकल्प का उपयोग बहुखण्डीय/फार्म डेटा का उपयोग करने लगता है। लेकिन अगर मैं एक अलग मल्टीपार्ट प्रकार निर्दिष्ट करने के प्रयास में हेडर निर्दिष्ट करता हूं, तो माइम सीमा जानकारी में अनुरोधों को जोड़ने की प्रतीत नहीं होती है।

url = 'http://10.10.10.90:8020/foo' 
headers = {'content-type': 'multipart/related'} 
files = {'submission': open('submission_set.xml', 'rb'), 'document': open('document.txt', 'rb')} 
response = requests.post(url, data=data, headers=headers) 
print response.text 

क्या अनुरोधों का उपयोग करके इसे करने का कोई तरीका है? या क्या कोई और उपकरण है जिसे मुझे देखना चाहिए?

+0

क्या आपने इन 22 प्रश्नों की जांच की है जो '[पायथन] [पायथन-अनुरोध] + मल्टीपार्ट 'की खोज के परिणामस्वरूप आये हैं? –

+3

@PiotrDobrogost: वे सभी 'मल्टीपार्ट/फॉर्म-डेटा' के बारे में हैं, जो 'अनुरोध' आपके लिए हैंडल करते हैं। यह * 'मल्टीपार्ट/संबंधित' * है, जो' POST' के लिए एक सामान्य एन्कोडिंग नहीं है और 'अनुरोध' स्वचालित रूप से संभाल नहीं करता है। –

उत्तर

19

आप माइम खुद एन्कोडिंग बनाना होगा। आप शायद एक चरित्र के रूप में अच्छी तरह से document प्रवेश के लिए निर्धारित सेट करना चाहते हैं

import requests 
from email.mime.multipart import MIMEMultipart 
from email.mime.text import MIMEText 

related = MIMEMultipart('related') 

submission = MIMEText('text', 'xml', 'utf8') 
submission.set_payload(open('submission_set.xml', 'rb').read()) 
related.attach(submission) 

document = MIMEText('text', 'plain') 
document.set_payload(open('document.txt', 'rb').read()) 
related.attach(document) 

body = related.as_string().split('\n\n', 1)[1] 
headers = dict(related.items()) 

r = requests.post(url, data=body, headers=headers) 

मैं एक्सएमएल फ़ाइल प्रकल्पित UTF-8 का उपयोग करता है,: आप email.mime पैकेज के साथ ऐसा कर सकते हैं।

requests केवल multipart/form-data पद निकायों बनाने का तरीका जानता है; multipart/related आमतौर पर उपयोग नहीं किया जाता है।

+0

धन्यवाद! यह बहुत उपयोगी है। मैंने वास्तव में पहले 'email.mime' पैकेज का उपयोग करने की कोशिश की, लेकिन यह समझ नहीं सका कि दोनों सेवाओं को एक साथ कैसे शादी करनी है। आपने मेरी दो वैकल्पिक स्क्रिप्ट को एक में विलय करने में मेरी मदद की! लेकिन वहाँ एक छोटी सी समस्या लगती है, और अगर यह सेवाओं या कुछ अन्य गलती का संयोजन है मैं नहीं बता सकता।मुझे [पंक्ति, कर्नल {अज्ञात-स्रोत}] पर प्रोलॉग में एक अप्रत्याशित ईओएफ मिल रहा है: [1,0] 'जो ऐसा लगता है कि भेजा जाने वाला पहला चरित्र ईओएफ के रूप में इंटरऑपरेट किया गया है। क्या यह उपकरण श्रृंखला/एन्कोडिंग के कारण हो सकता है? –

+0

मुझे बिल्कुल कोई जानकारी नहीं है; एक एक्सएमएल पार्सिंग समस्या की तरह लगता है, लेकिन त्रुटि परिचित नहीं है। –

+0

यह शानदार लग रहा है, लेकिन मेरा अनुरोध हमेशा के लिए लटका लगता है। कोई सुराग? – zapatilla

0

मैं requests और Google ड्राइव API "मल्टीपार्ट" अपलोड के साथ काम कर रहा हूं।

email.mime समाधान Google के एपीआई के साथ काम नहीं करता है, इसलिए मैंने requests स्रोत कोड में खोला यह देखने के लिए कि यह multipart/form-data निकायों को कैसे लागू करता है।

from urllib3.filepost import encode_multipart_formdata, choose_boundary 

def encode_multipart_related(fields, boundary=None): 
    if boundary is None: 
     boundary = choose_boundary() 

    body, _ = encode_multipart_formdata(fields, boundary) 
    content_type = str('multipart/related; boundary=%s' % boundary) 

    return body, content_type 

अब हम encode_multipart_related() का प्रयोग कर एक (body, content_type) टपल है कि गूगल की आवश्यकताओं से मेल खाता बनाने के लिए कर सकते हैं::

import json 
from urllib3.fields import RequestField 

def encode_media_related(metadata, media, media_content_type): 
    rf1 = RequestField(
     name='placeholder', 
     data=json.dumps(metadata), 
     headers={'Content-Type': 'application/json; charset=UTF-8'}, 
    ) 
    rf2 = RequestField(
     name='placeholder2', 
     data=media, 
     headers={'Content-Type': media_content_type}, 
    ) 
    return encode_multipart_related([rf1, rf2]) 

यहाँ एक है

requestsurllib3.filepost.encode_multipart_formdata() सहायक है, जो multipart/related प्रदान करने के लिए लपेटा जा सकता है का उपयोग करता है google_auth लाइब्रेरी का उपयोग करके Google ड्राइव पर हैलो वर्ल्ड फ़ाइल अपलोड करने के लिए हमारे encode_media_related() का पूरा उदाहरण उपयोग करता है।

from google.oauth2 import service_account 
import google.auth.transport.requests 

credentials = service_account.Credentials.from_service_account_file(
    PATH_TO_SERVICE_FILE, 
    scopes=['https://www.googleapis.com/auth/drive.file'], 
) 
session = google.auth.transport.requests.AuthorizedSession(credentials) 

metadata = { 
    'mimeType': 'application/vnd.google-apps.document', 
    'name': 'Test Upload', 
} 
body, content_type = encode_media_related(
    metadata, 
    '<html><body><p>Hello World!</body></html>', 
    'text/html; charset=UTF-8', 
) 
resp = session.post(
    'https://www.googleapis.com/upload/drive/v3/files', 
    data=body, 
    params={'uploadType': 'multipart'}, 
    headers={'Content-Type': content_type}, 
) 

print 'Uploaded to file with id: %s' % resp.json()['id'] 
संबंधित मुद्दे