¿Cómo cargar un archivo con solicitudes de Python?
Estoy realizando una tarea simple de cargar un archivo usando la biblioteca de solicitudes de Python. Busqué Stack Overflow y nadie parecía tener el mismo problema, es decir, 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 completando 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 entiendo
File file.txt of size bytes is uploaded successfully!
Query service results: There were 0 lines.
Que aparece sólo si el archivo está vacío. Así que no sé cómo enviar mi archivo correctamente. Sé que el archivo funciona porque si voy a este sitio web y completo el formulario manualmente, me devuelve una buena lista de objetos coincidentes, que es lo que busco. Realmente agradecería todas las sugerencias.
Algunos otros hilos relacionados (pero no responden a mi problema):
- Enviar archivo usando POST desde un script de Python
- http://docs.python-requests.org/en/latest/user/quickstart/#response-content
- Subir archivos usando solicitudes y enviar datos adicionales
- http://docs.python-requests.org/en/latest/user/advanced/#body-content-workflow
Si upload_file
pretende 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 requests
enviará un cuerpo POST de formulario de varias partes con el upload_file
campo configurado para el contenido del file.txt
archivo.
El nombre del archivo se incluirá en el encabezado MIME del 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.
Puedes usar una tupla para el files
valor del mapeo, con entre 2 y 4 elementos, si necesitas más control. El primer elemento es el nombre del archivo, seguido del contenido, 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 y un tipo de contenido alternativos, omitiendo los encabezados opcionales.
Si quiere decir que todo el cuerpo POST se tomará de un archivo (sin otros campos especificados), entonces no use el files
parámetro, simplemente publique el archivo directamente como data
. Es posible que también desees establecer un Content-Type
encabezado, ya que de lo contrario no se establecerá ninguno. Consulte Solicitudes de Python: POST datos desde un archivo .
(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
Subir cliente
Si desea cargar un solo archivo con requests
la biblioteca de Python, entonces Requests lib admite cargas de transmisión , lo que le permite enviar archivos o transmisiones de gran tamaño 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 un server.py
lado de manera que guarde la secuencia en un archivo sin cargarlo en la memoria. A continuación se muestra un ejemplo del 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 utilice werkzeug Form Data Parsing como se menciona en una solución para el problema de " cargas de archivos grandes que consumen memoria " para evitar el uso ineficiente de la memoria en la carga de archivos grandes (archivo de 22 GiB en ~60 segundos. El uso de la memoria es constante en aproximadamente 13 MB.).
@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