python solicita subir archivos

Estoy realizando una tarea sencilla de cargar un archivo utilizando la biblioteca de solicitudes de Python. Busqué en Stack Overflow y nadie parecía tener el mismo problema, a saber, que el servidor no recibe el archivo:

import requests url='http://nesssi.cacr.caltech.edu/cgi-bin/getmulticonedb_release2.cgi/post' files={'files': open('file.txt','rb')} values={'upload_file' : 'file.txt' , 'DB':'photcat' , 'OUT':'csv' , 'SHORT':'short'} r=requests.post(url,files=files,data=values) 

Estoy llenando el valor de la palabra clave ‘upload_file’ con mi nombre de archivo, porque si lo dejo en blanco, dice

 Error - You must select a file to upload! 

Y ahora me sale

 File file.txt of size bytes is uploaded successfully! Query service results: There were 0 lines. 

Que aparece solo si el archivo está vacío. Así que estoy atascado en cuanto a cómo enviar mi archivo con éxito. Sé que el archivo funciona porque si voy a este sitio web y lleno manualmente el formulario, devuelve una buena lista de objetos coincidentes, que es lo que busco. Realmente apreciaría todos los consejos.

Algunos otros hilos relacionados (pero no respondiendo a mi problema):

  • Enviar archivo usando POST desde un script de Python
  • http://docs.python-requests.org/en/latest/user/quickstart/#response-content
  • Cargar archivos utilizando peticiones y enviar datos extra.
  • http://docs.python-requests.org/en/latest/user/advanced/#body-content-workflow

Si upload_file está destinado a ser el archivo, use:

 files = {'upload_file': open('file.txt','rb')} values = {'DB': 'photcat', 'OUT': 'csv', 'SHORT': 'short'} r = requests.post(url, files=files, data=values) 

y las requests enviarán un cuerpo POST de formulario de varias partes con el campo upload_file establecido en el contenido del archivo file.txt .

El nombre del archivo se incluirá en el encabezado mime para el campo específico:

 >>> import requests >>> open('file.txt', 'wb') # create an empty demo file <_io.BufferedWriter name='file.txt'> >>> files = {'upload_file': open('file.txt', 'rb')} >>> print(requests.Request('POST', 'http://example.com', files=files).prepare().body.decode('ascii')) --c226ce13d09842658ffbd31e0563c6bd Content-Disposition: form-data; name="upload_file"; filename="file.txt" --c226ce13d09842658ffbd31e0563c6bd-- 

Tenga en cuenta el filename="file.txt" parámetro.

Puede usar una tupla para el valor de mapeo de files , con entre 2 y 4 elementos, si necesita más control. El primer elemento es el nombre de archivo, seguido del contenido, y un valor de encabezado de tipo de contenido opcional y una asignación opcional de encabezados adicionales:

 files = {'upload_file': ('foobar.txt', open('file.txt','rb'), 'text/x-spam')} 

Esto establece un nombre de archivo alternativo y un tipo de contenido, sin incluir los encabezados opcionales.

Si quiere decir que todo el cuerpo de POST debe tomarse de un archivo (sin otros campos especificados), entonces no use el parámetro de files , solo publique el archivo directamente como data . Es posible que también desee establecer un encabezado de Content-Type , ya que ninguno se configurará de otra manera.

(2018) la nueva biblioteca de solicitudes de Python ha simplificado este proceso, podemos usar la variable ‘archivos’ para indicar que queremos cargar un archivo codificado en varias partes

 url = 'http://httpbin.org/post' files = {'file': open('report.xls', 'rb')} r = requests.post(url, files=files) r.text 

Cliente uplaod

Si desea cargar un solo archivo con la biblioteca de requests Python, entonces las solicitudes lib son compatibles con las cargas de transmisión , lo que le permite enviar archivos o secuencias grandes sin leer en la memoria .

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

Lado del servidor

Luego almacene el archivo en el lado server.py manera que guarde la secuencia en un archivo sin cargar en la memoria. A continuación se muestra un ejemplo con el uso de cargas de archivos de Flask .

 @app.route("/upload", methods=['POST']) def upload_file(): from werkzeug.datastructures import FileStorage FileStorage(request.stream).save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) return 'OK', 200 

O use werkzeug Form Data Parsing como se menciona en una solución para el problema de ” cargas de archivos grandes que consumen memoria ” para evitar utilizar la memoria de manera ineficiente en la carga de archivos grandes (archivo st 22 GiB en ~ 60 segundos. El uso de la memoria es constante aproximadamente 13 MiB.).

 @app.route("/upload", methods=['POST']) def upload_file(): def custom_stream_factory(total_content_length, filename, content_type, content_length=None): import tempfile tmpfile = tempfile.NamedTemporaryFile('wb+', prefix='flaskapp', suffix='.nc') app.logger.info("start receiving file ... filename => " + str(tmpfile.name)) return tmpfile import werkzeug, flask stream, form, files = werkzeug.formparser.parse_form_data(flask.request.environ, stream_factory=custom_stream_factory) for fil in files.values(): app.logger.info(" ".join(["saved form name", fil.name, "submitted as", fil.filename, "to temporary file", fil.stream.name])) # Do whatever with stored file at `fil.stream.name` return 'OK', 200