Leggi i dati del file senza salvarli in Flask


112

Sto scrivendo la mia prima domanda di matraccio. Mi occupo del caricamento di file e in pratica quello che voglio è leggere i dati / contenuto del file caricato senza salvarlo e poi stamparlo sulla pagina risultante. Sì, presumo che l'utente carichi sempre un file di testo.

Ecco la semplice funzione di caricamento che sto utilizzando:

@app.route('/upload/', methods=['GET', 'POST'])
def upload():
    if request.method == 'POST':
        file = request.files['file']
        if file:
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            a = 'file uploaded'

    return render_template('upload.html', data = a)

In questo momento, sto salvando il file, ma quello che mi serve è quella variabile "a" per contenere il contenuto / i dati del file .. qualche idea?

Risposte:


137

FileStoragecontiene il streamcampo. Questo oggetto deve estendere IO o oggetto file, quindi deve contenere reade altri metodi simili. FileStorageanche estendere streamattributi campo Oggetto, quindi si può semplicemente utilizzare file.read()invece file.stream.read(). Inoltre è possibile utilizzare un saveargomento con dstparametro as StringIOo un altro oggetto IO o file da copiare FileStorage.streamin un altro oggetto IO o file.

Consulta la documentazione: http://flask.pocoo.org/docs/api/#flask.Request.files e http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.FileStorage .


1
esempio veloce:file = request.files.get('file') filetype = magic.from_buffer(file.read(1024))
endolith

7
ciao @ user2480542. Sto riscontrando lo stesso problema. Puoi descrivere come hai letto i contenuti del file caricato dal cliente? Sto chiamando file.read () ma non ricevo nulla. Grazie!
tmthyjames

1
@tmthyjames f = request.files['file']inserisce il file caricato (nella richiesta) in una var ("f"). Quindi f.read()funziona quindi utilizzando il codice sopra. quando print f.read()ottengo spazzatura dall'aspetto corretto nel terminale. Spero che aiuti.
Marc

6
Se stai caricando un file e hai un flusso binario, puoi convertirlo facilmente in un flusso di testo avvolgendolo in TextIOWrapper: mystring = TextIOWrapper(binary_stream)
Dutch Masters

7
f.read()non ha prodotto niente anche per me. La prima chiamata ha f.seek(0)fatto il trucco per me.
w177us

12

Se si desidera utilizzare elementi Flask standard, non è possibile evitare di salvare un file temporaneo se la dimensione del file caricato è> 500 kb. Se è inferiore a 500 kb, utilizzerà "BytesIO", che memorizza il contenuto del file in memoria, e se è superiore a 500 kb, memorizza il contenuto in TemporaryFile () (come indicato nella documentazione di werkzeug ). In entrambi i casi lo script si bloccherà fino a quando non verrà ricevuto l'intero file caricato.

Il modo più semplice per aggirare questo problema che ho trovato è:

1) Crea la tua classe IO simile a un file dove esegui tutta l'elaborazione dei dati in arrivo

2) Nel tuo script, sovrascrivi la classe Request con la tua:

class MyRequest( Request ):
  def _get_file_stream( self, total_content_length, content_type, filename=None, content_length=None ):
    return MyAwesomeIO( filename, 'w' )

3) Sostituisci la request_class di Flask con la tua:

app.request_class = MyRequest

4) Vai a bere un po 'di birra :)


0

Stavo cercando di fare la stessa identica cosa, aprire un file di testo (un CSV per Panda in realtà). Non voglio farne una copia, voglio solo aprirlo. Il modulo-WTF ha un bel browser di file, ma poi apre il file e crea un file temporaneo, che presenta come un flusso di memoria. Con un po 'di lavoro sotto il cofano,

form = UploadForm() 
 if form.validate_on_submit(): 
      filename = secure_filename(form.fileContents.data.filename)  
      filestream =  form.fileContents.data 
      filestream.seek(0)
      ef = pd.read_csv( filestream  )
      sr = pd.DataFrame(ef)  
      return render_template('dataframe.html',tables=[sr.to_html(justify='center, classes='table table-bordered table-hover')],titles = [filename], form=form) 

0

Condivido la mia soluzione (supponendo che tutto sia già configurato per connettersi a Google Bucket in Flask)

from google.cloud import storage

@app.route('/upload/', methods=['POST'])
def upload():
    if request.method == 'POST':
        # FileStorage object wrapper
        file = request.files["file"]                    
        if file:
            os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = app.config['GOOGLE_APPLICATION_CREDENTIALS']
            bucket_name = "bucket_name" 
            storage_client = storage.Client()
            bucket = storage_client.bucket(bucket_name)
            # Upload file to Google Bucket
            blob = bucket.blob(file.filename) 
            blob.upload_from_string(file.read())

Il mio post

Direttamente a Google Bucket in boccetta


-1

Abbiamo semplicemente fatto:

import io
from pathlib import Path

    def test_my_upload(self, accept_json):
        """Test my uploads endpoint for POST."""
        data = {
            "filePath[]": "/tmp/bin",
            "manifest[]": (io.StringIO(str(Path(__file__).parent /
                                           "path_to_file/npmlist.json")).read(),
                           'npmlist.json'),
        }
        headers = {
            'a': 'A',
            'b': 'B'
        }
        res = self.client.post(api_route_for('/test'),
                               data=data,
                               content_type='multipart/form-data',
                               headers=headers,
                               )
        assert res.status_code == 200

-1

in funzione

def handleUpload():
    if 'photo' in request.files:
        photo = request.files['photo']
        if photo.filename != '':      
            image = request.files['photo']  
            image_string = base64.b64encode(image.read())
            image_string = image_string.decode('utf-8')
            #use this to remove b'...' to get raw string
            return render_template('handleUpload.html',filestring = image_string)
    return render_template('upload.html')

nel file html

<html>
<head>
    <title>Simple file upload using Python Flask</title>
</head>
<body>
    {% if filestring %}
      <h1>Raw image:</h1>
      <h1>{{filestring}}</h1>
      <img src="data:image/png;base64, {{filestring}}" alt="alternate" />.
    {% else %}
      <h1></h1>
    {% endif %}
</body>


-2

Nel caso in cui vogliamo scaricare il file in memoria su disco. Questo codice può essere utilizzato

  if isinstanceof(obj,SpooledTemporaryFile):
    obj.rollover()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.