2010-03-23 11 views
13

स्ट्रीमिंग के साथ एक बड़ी फ़ाइल पोस्ट करें मैं संभावित रूप से बड़ी फ़ाइलों को वेब सर्वर पर अपलोड कर रहा हूं। वर्तमान में मैं यह कर रहा हूं:पायथन: HTTP

import urllib2 

f = open('somelargefile.zip','rb') 
request = urllib2.Request(url,f.read()) 
request.add_header("Content-Type", "application/zip") 
response = urllib2.urlopen(request) 

हालांकि, यह पोस्ट करने से पहले पूरी फ़ाइल की सामग्री को स्मृति में पढ़ता है। मैं इसे सर्वर पर फ़ाइल कैसे स्ट्रीम कर सकता हूं?

+0

संबंधित

with open('massive-body', 'rb') as f: requests.post('http://some.url/streamed', data=f) 

कर सकते हैं: [WSGI फ़ाइल एक जनरेटर के साथ स्ट्रीमिंग] (http : //stackoverflow.com/questions/11811404/) –

+0

संबंधित: http://stackoverflow.com/questions/2502596/python-http-post-a-large-file-with- स्ट्रीमिंग –

उत्तर

23

systempuntoout से जुड़े मेलिंग सूची थ्रेड के माध्यम से पढ़ना, मुझे समाधान की ओर एक सुराग मिला।

mmap मॉड्यूल आपको एक स्ट्रिंग की तरह कार्य करने वाली फ़ाइल खोलने की अनुमति देता है। फ़ाइल के हिस्सों को मांग पर स्मृति में लोड किया जाता है।

यहाँ कोड मैं अब का उपयोग कर रहा है:

import urllib2 
import mmap 

# Open the file as a memory mapped string. Looks like a string, but 
# actually accesses the file behind the scenes. 
f = open('somelargefile.zip','rb') 
mmapped_file_as_string = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) 

# Do the request 
request = urllib2.Request(url, mmapped_file_as_string) 
request.add_header("Content-Type", "application/zip") 
response = urllib2.urlopen(request) 

#close everything 
mmapped_file_as_string.close() 
f.close() 
+0

खुशी हुई यह मदद की :) – systempuntoout

+0

यह काम नहीं कर रहा है मुझे यूआरएल त्रुटि मिल रही है – TinTin

+0

क्या आप कृपया नीचे दी गई पंक्ति की पुष्टि कर सकते हैं: request = urllib2।अनुरोध (url, mmapped_file_as_string) – TinTin

3

क्या आपने Mechanize के साथ प्रयास किया है?

from mechanize import Browser 
br = Browser() 
br.open(url) 
br.form.add_file(open('largefile.zip'), 'application/zip', 'largefile.zip') 
br.submit() 

या, आप, बहुखण्डीय/फार्म डेटा का उपयोग जाँच this पुराने पोस्ट करने के लिए नहीं करना चाहते हैं।

1. Use mmap, Memory Mapped file object 
    2. Patch httplib.HTTPConnection.send 
+1

मैं भेजना नहीं चाहता फ़ाइलें एन्क्यू oded "मल्टीपार्ट/फॉर्म-डेटा"। ऐसा लगता है कि ऐसा लगता है। मैं सिर्फ कच्ची पोस्ट की तलाश में हूं। –

+0

पायथन पर 2.7 विकल्प # 2 को पहले ही पैच किया गया है, ब्लॉक आकार 8192 है, मुझे आश्चर्य है कि क्यों .. हम्म। इस पर मानक/मानक क्या है? – MistahX

1

कोशिश pycurl:

यह दो विकल्प पता चलता है। मेरे पास कोई भी सेटअप सेटअप नहीं है जो मल्टीपार्ट/फॉर्म-डेटा पोस्ट में नहीं है, लेकिन यहां एक साधारण उदाहरण है जो फ़ाइल को आवश्यकतानुसार पढ़ता है।

import os 
import pycurl 

class FileReader: 
    def __init__(self, fp): 
     self.fp = fp 
    def read_callback(self, size): 
     return self.fp.read(size) 

c = pycurl.Curl() 
c.setopt(pycurl.URL, url) 
c.setopt(pycurl.UPLOAD, 1) 
c.setopt(pycurl.READFUNCTION, FileReader(open(filename, 'rb')).read_callback) 
filesize = os.path.getsize(filename) 
c.setopt(pycurl.INFILESIZE, filesize) 
c.perform() 
c.close() 
+1

धन्यवाद जिमबी। मैंने इसका इस्तेमाल किया होगा, सिवाय इसके कि मेरे पास कुछ लोग विंडोज इसका उपयोग कर रहे हैं, और मैं नहीं चाहता कि उन्हें कुछ और इंस्टॉल करना पड़े। –

3

प्रलेखन कहना नहीं है कि आप यह कर सकते हैं, लेकिन urllib2 में कोड (और httplib) के रूप में पढ़ने() विधि के साथ किसी भी वस्तु को स्वीकार करता है डेटा। तो एक खुली फ़ाइल का उपयोग कर चाल करना प्रतीत होता है।

आपको सामग्री-लंबाई शीर्षलेख स्वयं सेट करने की आवश्यकता होगी। यदि यह सेट नहीं है, तो urllib2 डेटा पर लेन() को कॉल करेगा, जो फ़ाइल ऑब्जेक्ट्स का समर्थन नहीं करते हैं।

import os.path 
import urllib2 

data = open(filename, 'r') 
headers = { 'Content-Length' : os.path.getsize(filename) } 
response = urllib2.urlopen(url, data, headers) 

यह प्रासंगिक कोड है जो आपके द्वारा प्रदान किए जाने वाले डेटा को संभालता है। यह अजगर 2.7 में httplib.py में HTTPConnection वर्ग से है:

def send(self, data): 
    """Send `data' to the server.""" 
    if self.sock is None: 
     if self.auto_open: 
      self.connect() 
     else: 
      raise NotConnected() 

    if self.debuglevel > 0: 
     print "send:", repr(data) 
    blocksize = 8192 
    if hasattr(data,'read') and not isinstance(data, array): 
     if self.debuglevel > 0: print "sendIng a read()able" 
     datablock = data.read(blocksize) 
     while datablock: 
      self.sock.sendall(datablock) 
      datablock = data.read(blocksize) 
    else: 
     self.sock.sendall(data) 
0

requests पुस्तकालय का उपयोग करके आप के रूप में उल्लेख here in their docs

+0

8K ब्लॉक आकार अभी भी लागू होता है, जैसा कि fansplib.py, भेजता है() एल # 869 कहा जाता है। –

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