Lire les données du fichier sans les enregistrer dans Flask


112

J'écris ma première application flask. Je m'occupe des téléchargements de fichiers, et essentiellement ce que je veux, c'est lire les données / contenu du fichier téléchargé sans l'enregistrer, puis l'imprimer sur la page résultante. Oui, je suppose que l'utilisateur télécharge toujours un fichier texte.

Voici la fonction de téléchargement simple que j'utilise:

@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)

En ce moment, j'enregistre le fichier, mais ce dont j'ai besoin est que "une" variable contienne le contenu / les données du fichier .. des idées?

Réponses:


137

FileStoragecontient un streamchamp. Cet objet doit étendre IO ou objet fichier, il doit donc contenir readet d'autres méthodes similaires. FileStorageétendez également streamles attributs des objets de champ, vous pouvez donc simplement les utiliser à la file.read()place file.stream.read(). Vous pouvez également utiliser l' saveargument avec le dstparamètre comme StringIOou un autre objet IO ou fichier pour copier FileStorage.streamvers un autre objet IO ou fichier.

Voir la documentation: http://flask.pocoo.org/docs/api/#flask.Request.files et http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.FileStorage .


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

7
salut @ user2480542. Je rencontre le même problème. Pouvez-vous décrire comment vous avez lu le contenu du fichier téléchargé par le client? J'appelle file.read () mais je n'obtiens rien. Merci!
tmthyjames

1
@tmthyjames f = request.files['file']place le fichier téléchargé (dans la requête) dans un var ("f"). Ensuite, f.read()fonctionne en utilisant le code ci-dessus. quand est-ce que print f.read()je reçois des fichiers indésirables dans le terminal. J'espère que cela pourra aider.
Marc

6
Si vous téléchargez un fichier et avez un flux binaire, vous pouvez facilement le convertir en flux de texte en l'enveloppant dans TextIOWrapper: mystring = TextIOWrapper(binary_stream)
Dutch Masters

7
f.read()n'a rien cédé pour moi aussi. L'appel a d'abord f.seek(0)fait l'affaire pour moi.
w177us

12

Si vous souhaitez utiliser des éléments Flask standard, il n'y a aucun moyen d'éviter d'enregistrer un fichier temporaire si la taille du fichier téléchargé est> 500 Ko. S'il est inférieur à 500kb - il utilisera "BytesIO", qui stocke le contenu du fichier en mémoire, et s'il est supérieur à 500kb - il stocke le contenu dans TemporaryFile () (comme indiqué dans la documentation werkzeug ). Dans les deux cas, votre script se bloquera jusqu'à ce que l'intégralité du fichier téléchargé soit reçue.

Le moyen le plus simple de contourner ce problème que j'ai trouvé est:

1) Créez votre propre classe IO de type fichier où vous effectuez tout le traitement des données entrantes

2) Dans votre script, remplacez la classe Request par la vôtre:

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

3) Remplacez le request_class de Flask par le vôtre:

app.request_class = MyRequest

4) Allez boire de la bière :)


0

J'essayais de faire exactement la même chose, ouvrir un fichier texte (un CSV pour Pandas en fait). Je ne veux pas en faire une copie, je veux juste l'ouvrir. Le form-WTF a un bon navigateur de fichiers, mais ensuite il ouvre le fichier et crée un fichier temporaire, qu'il présente comme un flux mémoire. Avec un peu de travail sous le capot,

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

Je partage ma solution (en supposant que tout est déjà configuré pour se connecter à google bucket dans 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())

Mon message

Direct vers Google Bucket dans flask


-1

Nous avons simplement fait:

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

en fonction

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')

dans un fichier 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

Dans le cas où nous voulons vider le fichier en mémoire sur le disque. Ce code peut être utilisé

  if isinstanceof(obj,SpooledTemporaryFile):
    obj.rollover()
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.