Buscar..


Sintaxis

  • request.files ['name'] # único archivo requerido
  • request.files.get ('nombre') # Ninguno si no está publicado
  • request.files.getlist ('nombre') # lista de cero o más archivos publicados
  • CombinedMultiDict ((request.files, request.form)) # combina datos de formulario y archivo

Cargando archivos

Formulario HTML

  • Utilice una entrada de tipo de file y el navegador proporcionará un campo que le permite al usuario seleccionar un archivo para cargar.
  • Sólo forma con el post método puede enviar datos de archivo.
  • Asegúrese de establecer el enctype=multipart/form-data . De lo contrario, se enviará el nombre del archivo, pero no los datos del archivo.
  • Use el atributo multiple en la entrada para permitir la selección de múltiples archivos para el campo único.
<form method=post enctype=multipart/form-data>
    <!-- single file for the "profile" field -->
    <input type=file name=profile>
    <!-- multiple files for the "charts" field -->
    <input type=file multiple name=charts>
    <input type=submit>
</form>

Solicitudes de Python

Requests es una potente biblioteca de Python para realizar solicitudes HTTP. Puede usarlo (u otras herramientas) para publicar archivos sin un navegador.

  • Abre los archivos para leer en modo binario.
  • Hay múltiples estructuras de datos que los files toman. Esto demuestra una lista de tuplas (name, data) , que permite múltiples archivos como el formulario anterior.
import requests

with open('profile.txt', 'rb') as f1, open('chart1.csv', 'rb') as f2, open('chart2.csv', 'rb') as f3:
    files = [
        ('profile', f1),
        ('charts', f2),
        ('charts', f3)
    ]
    requests.post('http://localhost:5000/upload', files=files)

Esto no pretende ser una lista exhaustiva. Para ver ejemplos de uso de su herramienta favorita o escenarios más complejos, consulte la documentación de esa herramienta.

Guardar subidas en el servidor

Los archivos cargados están disponibles en request.files , un MultiDict campo de asignación MultiDict a objetos de archivo. Use getlist , en lugar de [] u get , si se getlist varios archivos con el mismo nombre de campo.

request.files['profile']  # single file (even if multiple were sent)
request.files.getlist('charts')  # list of files (even if one was sent)

Los objetos en request.files tienen un método de save que guarda el archivo localmente. Crear un directorio común para guardar los archivos.

El atributo de filename es el nombre con el que se cargó el archivo. Esto puede ser establecido arbitrariamente por el cliente, así que páselo a través del método secure_filename para generar un nombre válido y seguro para guardarlo. Esto no garantiza que el nombre sea único , por lo que los archivos existentes se sobrescribirán a menos que haga un trabajo extra para detectar eso.

import os
from flask import render_template, request, redirect, url_for
from werkzeug import secure_filename

# Create a directory in a known location to save files to.
uploads_dir = os.path.join(app.instance_path, 'uploads')
os.makedirs(uploads_dir, exists_ok=True)

@app.route('/upload', methods=['GET', 'POST'])
def upload():
    if request.method == 'POST':
        # save the single "profile" file
        profile = request.files['profile']
        profile.save(os.path.join(uploads_dir, secure_filename(profile.filename)))

        # save each "charts" file
        for file in request.files.getlist('charts'):
            file.save(os.path.join(uploads_dir, secure_filename(file.name)))

        return redirect(url_for('upload'))

    return render_template('upload.html')

Pasando datos a WTForms y Flask-WTF

WTForms proporciona un FileField para representar una entrada de tipo de archivo. No hace nada especial con los datos cargados. Sin embargo, dado que Flask divide los datos del formulario ( request.form ) y los datos del archivo ( request.files ), debe asegurarse de pasar los datos correctos al crear el formulario. Puede usar un CombinedMultiDict para combinar los dos en una única estructura que WTForms entiende.

form = ProfileForm(CombinedMultiDict((request.files, request.form)))

Si está utilizando Flask-WTF , una extensión para integrar Flask y WTForms, el manejo de los datos correctos se realizará de manera automática.

Debido a un error en WTForms, solo un archivo estará presente para cada campo, incluso si se cargaron múltiples. Vea este tema para más detalles. Se arreglará en 3.0.

PARSE CSV ARCHIVO DE CARGA COMO LISTA DE DICCIONARIOS EN FLASK SIN AHORRO

Los desarrolladores a menudo necesitan diseñar sitios web que permitan a los usuarios cargar un archivo CSV. Por lo general, no hay razón para guardar el archivo CSV real, ya que los datos se procesarán y / o almacenarán en una base de datos una vez que se carguen. Sin embargo, muchos, si no la mayoría, de los métodos PYTHON de análisis de datos CSV requieren que los datos se lean como un archivo. Esto puede presentar un poco de dolor de cabeza si está utilizando FLASK para el desarrollo web.

Supongamos que nuestro CSV tiene una fila de encabezado y se parece a lo siguiente:

h1,h2,h3
'yellow','orange','blue'
'green','white','black'
'orange','pink','purple'

Ahora, supongamos que el formulario html para cargar un archivo es el siguiente:

<form action="upload.html" method="post" enctype="multipart/form-data">
    <input type="file" name="fileupload" id="fileToUpload">
    <input type="submit" value="Upload File" name="submit">
</form>

Como nadie quiere reinventar la rueda, usted decide IMPORTAR csv en su script de FLASK . No hay garantía de que las personas suban el archivo csv con las columnas en el orden correcto. Si el archivo csv tiene una fila de encabezado, con la ayuda del método csv.DictReader puede leer el archivo CSV como una lista de diccionarios, con las entradas en la fila del encabezado. Sin embargo, csv.DictReader necesita un archivo y no acepta cadenas directamente. Puede pensar que necesita usar los métodos de FLASK para guardar primero el archivo cargado, obtener el nuevo nombre y ubicación del archivo, abrirlo con csv.DictReader y luego eliminar el archivo. Parece un poco de un desperdicio.

Afortunadamente, podemos obtener el contenido del archivo como una cadena y luego dividir la cadena por líneas terminadas. El método csv csv.DictReader aceptará esto como un sustituto de un archivo. El siguiente código muestra cómo se puede lograr esto sin guardar temporalmente el archivo.

@application.route('upload.html',methods = ['POST'])
def upload_route_summary():
    if request.method == 'POST':

        # Create variable for uploaded file
        f = request.files['fileupload']  

        #store the file contents as a string
        fstring = f.read()
        
        #create list of dictionaries keyed by header row
        csv_dicts = [{k: v for k, v in row.items()} for row in csv.DictReader(fstring.splitlines(), skipinitialspace=True)]

        #do something list of dictionaries
    return "success"

La variable csv_dicts es ahora la siguiente lista de diccionarios:

   csv_dicts = 
    [
        {'h1':'yellow','h2':'orange','h3':'blue'},
        {'h1':'green','h2':'white','h3':'black'},
        {'h1':'orange','h2':'pink','h3':'purple'}
    ]

En caso de que sea nuevo en PYTHON, puede acceder a datos como los siguientes:

csv_dicts[1]['h2'] = 'white'
csv_dicts[0]['h3'] = 'blue'

Otras soluciones implican importar el módulo io y usar el método io.Stream . Siento que este es un enfoque más directo. Creo que el código es un poco más fácil de seguir que usar el método io . Este enfoque es específico del ejemplo de analizar un archivo CSV cargado.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow