Streaming POST un archivo grande a CherryPy por el cliente de Python

Quiero enviar un archivo grande desde un cliente de Python a cherrypy. Estoy usando la biblioteca de solicitudes.

Este es mi código de cliente:

def upload(fileName=None): url = 'http://localhost:8080/upload' files = {'myFile': ( fileName, open(fileName, 'rb') )} r = requests.post(url, files=files) #with open(fileName,'rb') as payload: #headers = {'content-type': 'multipart/form-data'} #r = requests.post('http://127.0.0.1:8080', data=payload,verify=False,headers=headers) if __name__ == '__main__': upload(sys.argv[1]) 

El problema es que esto pone todo el archivo en la memoria RAM. ¿Hay alguna manera de POSTAR el archivo en pedazos?

 class FileDemo(object): @cherrypy.expose def upload(self, myFile): print myFile.filename #size = 0 #decoder = MultipartDecoder(myFile, 'image/jpeg') #for part in decoder.parts: #print(part.header['content-type']) #while True: #advances to the content that hasn't been read #myFile.file.seek(size, 0) #reads 100mb at a time so it doesn't fill up the RAM #data = myFile.file.read(10240000) #newFile = open("/home/ivo/Desktop/"+str(myFile.filename), 'a+') #newFile.write(data) #newFile.close #size += len(data) #if len(data) < 10240000: #break if __name__ == '__main__': cherrypy.quickstart(FileDemo()) 

Este es el código en el lado del servidor. Tiene muchos comentarios porque he estado probando muchas cosas. Ahora mismo estoy imprimiendo el nombre del archivo y el cliente todavía transfiere todo el archivo a la RAM.

No sé qué más probar. Gracias de antemano por su ayuda.

Si se trata de una carga específica de CherryPy, puede omitir los obstáculos de encoding de multipart/form-data y simplemente enviar el contenido de los archivos de POST de transmisión.

cliente

 #!/usr/bin/env python # -*- coding: utf-8 -*- import urllib2 import io import os class FileLenIO(io.FileIO): def __init__(self, name, mode = 'r', closefd = True): io.FileIO.__init__(self, name, mode, closefd) self.__size = statinfo = os.stat(name).st_size def __len__(self): return self.__size f = FileLenIO('/home/user/Videos/video.mp4', 'rb') request = urllib2.Request('http://127.0.0.1:8080/upload', f) request.add_header('Content-Type', 'application/octet-stream') # you can add custom header with filename if you need it response = urllib2.urlopen(request) print response.read() 

servidor

 #!/usr/bin/env python # -*- coding: utf-8 -*- import os import tempfile import shutil import cherrypy config = { 'global' : { 'server.socket_host' : '127.0.0.1', 'server.socket_port' : 8080, 'server.thread_pool' : 8, # remove any limit on the request body size; cherrypy's default is 100MB 'server.max_request_body_size' : 0, # increase server socket timeout to 60s; cherrypy's defult is 10s 'server.socket_timeout' : 60 } } class App: @cherrypy.config(**{'response.timeout': 3600}) # default is 300s @cherrypy.expose() def upload(self): '''Handle non-multipart upload''' destination = os.path.join('/home/user/test-upload') with open(destination, 'wb') as f: shutil.copyfileobj(cherrypy.request.body, f) return 'Okay' if __name__ == '__main__': cherrypy.quickstart(App(), '/', config) 

Probado en archivo de video 1.3GiB. El consumo de memoria del lado del servidor es inferior a 10MiB, el cliente es inferior a 5MiB.

Así es como resolví el problema:

cliente

 import poster def upload(fileName=None): register_openers() url = 'http://localhost:8080/upload' data, headers = multipart_encode({"myFile": open(fileName, "rb")}) request = urllib2.Request(url, data, headers) request.unverifiable = True response = urllib2.urlopen(request) the_page = response.read() if __name__ == '__main__': upload(sys.argv[1]) 

servidor

 @cherrypy.expose def upload(self, myFile): cherrypy.response.timeout = 3600 newFile = open("/home/ivo/Desktop/"+str(myFile.filename), 'a+') newFile.write(myFile.file.read()) newFile.close