2012-07-18 29 views
8

ठीक है,पोस्ट अनुरोध के शरीर को

यह आसान होना चाहिए, क्योंकि लोग इसे हर समय करते हैं। मैं एक POST अनुरोध के शरीर को एक मोड़ Agent भेजना चाहता हूं। यह एक मोड़ FileBodyProducer के साथ बनाया गया है। सर्वर की तरफ, मुझे render_POST विधि के लिए request ऑब्जेक्ट मिलता है।

मैं शरीर को कैसे पुनर्प्राप्त करूं?

सर्वर:

from twisted.web import server, resource 
from twisted.internet import reactor 


class Simple(resource.Resource): 
    isLeaf = True 
    def render_GET(self, request): 
     return "{0}".format(request.args.keys()) 
    def render_POST(self, request): 
     return "{0}".format(request.data) 
     with open(request.args['filename'][0], 'rb') as fd: 
      fd.write(request.write()) 

site = server.Site(Simple()) 
reactor.listenTCP(8080, site) 
reactor.run() 

ग्राहक:

from StringIO import StringIO 

from twisted.internet import reactor 
from twisted.web.client import Agent 
from twisted.web.http_headers import Headers 

from twisted.web.client import FileBodyProducer 
from twisted.internet.defer import Deferred 
from twisted.internet.protocol import Protocol 
from pprint import pformat 

class BeginningPrinter(Protocol): 
    def __init__(self, finished): 
     self.finished = finished 
     self.remaining = 1024 * 10 

    def dataReceived(self, bytes): 
     if self.remaining: 
      display = bytes[:self.remaining] 
      print 'Some data received:' 
      print display 
      self.remaining -= len(display) 

    def connectionLost(self, reason): 
     print 'Finished receiving body:', reason.getErrorMessage() 
     self.finished.callback(None) 

agent = Agent(reactor) 
body = FileBodyProducer(StringIO("hello, world")) 
d = agent.request(
    'POST', 
    'http://127.0.0.1:8080/', 
    Headers({'User-Agent': ['Twisted Web Client Example'], 
      'Content-Type': ['text/x-greeting']}), 
    body) 

def cbRequest(response): 
    print 'Response version:', response.version 
    print 'Response code:', response.code 
    print 'Response phrase:', response.phrase 
    print 'Response headers:' 
    print pformat(list(response.headers.getAllRawHeaders())) 
    finished = Deferred() 
    response.deliverBody(BeginningPrinter(finished)) 
    return finished 
d.addCallback(cbRequest) 

def cbShutdown(ignored): 
    reactor.stop() 
d.addBoth(cbShutdown) 

reactor.run() 

केवल डॉक्स मैं उपभोक्ता पक्ष leave something to be desired स्थापित करने के लिए मिल सकता है। मुख्य रूप से, उपभोक्ता विधि पर परिणाम प्राप्त करने का तरीका कैसे उपयोग कर सकता है?

मुझे इन दोनों घटकों को एकसाथ प्लग करने के लिए कौन सा गुम है?

उत्तर

13

ठीक है, तो यह request.content.read() पर कॉल करने जितना सरल है। यह, जहां तक ​​मैं कह सकता हूं, API में अनियंत्रित है।

from twisted.internet import reactor 
from twisted.web.client import Agent 
from twisted.web.http_headers import Headers 

from twisted.web.client import FileBodyProducer 
from twisted.internet.defer import Deferred 
from twisted.internet.protocol import Protocol 
from pprint import pformat 

class BeginningPrinter(Protocol): 
    def __init__(self, finished): 
     self.finished = finished 
     self.remaining = 1024 * 10 

    def dataReceived(self, bytes): 
     if self.remaining: 
      display = bytes[:self.remaining] 
      print 'Some data received:' 
      print display 
      self.remaining -= len(display) 

    def connectionLost(self, reason): 
     print 'Finished receiving body:', reason.getErrorMessage() 
     self.finished.callback(None) 

class SaveContents(Protocol): 
    def __init__(self, finished, filesize, filename): 
     self.finished = finished 
     self.remaining = filesize 
     self.outfile = open(filename, 'wb') 

    def dataReceived(self, bytes): 
     if self.remaining: 
      display = bytes[:self.remaining] 
      self.outfile.write(display) 
      self.remaining -= len(display) 
     else: 
      self.outfile.close() 

    def connectionLost(self, reason): 
     print 'Finished receiving body:', reason.getErrorMessage() 
     self.outfile.close() 
     self.finished.callback(None) 

agent = Agent(reactor) 
f = open('70935-new_barcode.pdf', 'rb') 
body = FileBodyProducer(f) 
d = agent.request(
    'POST', 
    'http://127.0.0.1:8080?filename=test.pdf', 
    Headers({'User-Agent': ['Twisted Web Client Example'], 
      'Content-Type': ['multipart/form-data; boundary=1024'.format()]}), 
    body) 

def cbRequest(response): 
    print 'Response version:', response.version 
    print 'Response code:', response.code 
    print 'Response phrase:', response.phrase 
    print 'Response headers:' 
    print 'Response length:', response.length 
    print pformat(list(response.headers.getAllRawHeaders())) 
    finished = Deferred() 
    response.deliverBody(SaveContents(finished, response.length, 'test2.pdf')) 
    return finished 
d.addCallback(cbRequest) 

def cbShutdown(ignored): 
    reactor.stop() 
d.addBoth(cbShutdown) 

reactor.run() 

और यहाँ सर्वर है::

from twisted.web import server, resource 
from twisted.internet import reactor 
import os 

# multi part encoding example: http://marianoiglesias.com.ar/python/file-uploading-with-multi-part-encoding-using-twisted/ 
class Simple(resource.Resource): 
    isLeaf = True 
    def render_GET(self, request): 
     return "{0}".format(request.args.keys()) 
    def render_POST(self, request): 
     with open(request.args['filename'][0], 'wb') as fd: 
      fd.write(request.content.read()) 
     request.setHeader('Content-Length', os.stat(request.args['filename'][0]).st_size) 
     with open(request.args['filename'][0], 'rb') as fd: 
      request.write(fd.read()) 
     request.finish() 
     return server.NOT_DONE_YET 

site = server.Site(Simple()) 
reactor.listenTCP(8080, site) 
reactor.run() 

मैं अब फ़ाइल सामग्री मैं प्राप्त लिख सकते हैं, और परिणाम वापस पढ़ें

यहाँ ग्राहक के लिए अद्यतन कोड है।

+0

भविष्य के संदर्भ के लिए, मैं os.stat() st_size द्वारा सामग्री-लंबाई सेट के साथ request.write (fd.read()) नहीं करने की अनुशंसा करता हूं। मुझे एक मुद्दा था जहां मुझे अनुरोध पर डिवाइस पर IOError कोई स्थान नहीं छोड़ा गया था। लिखना (fd.read())। यदि आपके पास स्मृति है, तो मैं फ़ाइल को पहले बफर में पढ़ने की सिफारिश करता हूं, और फिर लेन (buf) के आधार पर सामग्री-लंबाई कर रहा हूं। फिर request.write (buf)। –

2

यदि सामग्री का प्रकार एप्लिकेशन/एक्स-www-form-urlencoded या multipart/form-data, है, तो शरीर को पार्स किया जाएगा और request.args dict।

यदि शरीर बहुत बड़ा है, तो यह temp फ़ाइल में लिखा जाता है, अन्यथा स्ट्रिंगियो में।

शरीर को पढ़ने के बाद, विधि खत्म() कहा जाता है। आप उपclass अनुरोध कर सकते हैं और शरीर को इस विधि में रखता है या अन्यथा करता है।

0

आप

d = httpRequest('htpp://...', post_data_as_dictionary, some_headers, 'POST') 
d.addCallback(your_ok_callback_function) 
d.addErrback(your_errorback_function) 

उदाहरण हेडर यानी कर सकते हैं एक सरल शरीर के साथ (एक फ़ाइल नहीं) पोस्ट बनाने के लिए आप कर सकते हैं के रूप में वास्तविक कोड में ऊपर का उपयोग करने के

import urllib 
from twisted.internet import protocol 
from twisted.internet import defer 
from twisted.web.http_headers import Headers 
from twisted.internet import reactor 
from twisted.web.client import Agent 
from twisted.web.iweb import IBodyProducer 
from zope.interface import implements 
from twisted.internet.defer import succeed 

class StringProducer(object): 
    implements(IBodyProducer) 

    def __init__(self, body): 
     self.body = body 
     self.length = len(body) 

    def startProducing(self, consumer): 
     consumer.write(self.body) 
     return succeed(None) 

    def pauseProducing(self): 
     pass 

    def stopProducing(self): 
     pass 

class SimpleReceiver(protocol.Protocol): 
    def __init__(self, d): 
     self.buf = ''; self.d = d 

    def dataReceived(self, data): 
     self.buf += data 

    def connectionLost(self, reason): 
     self.d.callback(self.buf) 

def httpRequest(url, values=None, headers=None, method='POST'): 

    agent = Agent(reactor) 
    data = urllib.urlencode(values) if values else None 

    d = agent.request(method, url, Headers(headers) if headers else {}, 
     StringProducer(data) if data else None 
     ) 

    def handle_response(response): 
     if response.code == 204: 
      d = defer.succeed('') 
     else: 
      d = defer.Deferred() 
      response.deliverBody(SimpleReceiver(d)) 
     return d 

    d.addCallback(handle_response) 
    return d 

इस प्रकार अब चाहते हैं जैसे

headers = {'Accept' : ['application/json',], 
      'Content-Type': ['application/x-www-form-urlencoded',] 
} 

दिखना चाहिए मुझे आशा है कि मदद करता है

संबंधित मुद्दे