Lesen Sie die Dateidaten, ohne sie in Flask zu speichern


112

Ich schreibe meine erste Kolbenanwendung. Ich habe es mit Datei-Uploads zu tun, und im Grunde möchte ich die Daten / Inhalte der hochgeladenen Datei lesen, ohne sie zu speichern, und sie dann auf der resultierenden Seite drucken. Ja, ich gehe davon aus, dass der Benutzer immer eine Textdatei hochlädt.

Hier ist die einfache Upload-Funktion, die ich verwende:

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

Im Moment speichere ich die Datei, aber ich brauche diese 'a'-Variable, um den Inhalt / die Daten der Datei zu enthalten. Irgendwelche Ideen?

Antworten:


137

FileStorageenthält streamFeld. Dieses Objekt muss das E / A- oder Dateiobjekt erweitern, daher muss es readähnliche Methoden enthalten. FileStorageErweitern streamSie auch Feldobjektattribute , sodass Sie file.read()stattdessen einfach verwenden können file.stream.read(). Sie können auch saveArgumente mit dstParametern als StringIOoder einem anderen E / A- oder Dateiobjekt verwenden, um sie FileStorage.streamin ein anderes E / A- oder Dateiobjekt zu kopieren .

Siehe Dokumentation: http://flask.pocoo.org/docs/api/#flask.Request.files und http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.FileStorage .


1
schnelles Beispiel:file = request.files.get('file') filetype = magic.from_buffer(file.read(1024))
Endolith

7
hi @ user2480542. Ich habe das gleiche Problem. Können Sie beschreiben, wie Sie den Inhalt der vom Client hochgeladenen Datei gelesen haben? Ich rufe file.read () auf, bekomme aber nichts. Vielen Dank!
tmthyjames

1
@tmthyjames fügt f = request.files['file']die hochgeladene Datei (in der Anfrage) in eine Variable ("f") ein. Dann f.read()funktioniert dann mit dem obigen Code. Wann print f.read()bekomme ich richtig aussehenden Müll im Terminal? Hoffentlich hilft das.
Marc

6
Wenn Sie eine Datei hochladen und einen Binär-Stream haben, können Sie ihn einfach in einen Text-Stream konvertieren, indem Sie ihn in TextIOWrapper einbinden: mystring = TextIOWrapper(binary_stream)
Dutch Masters

6
f.read()hat mir auch nichts gebracht. Das erste Anrufen f.seek(0)hat den Trick für mich getan.
w177us

11

Wenn Sie Standard-Flask-Inhalte verwenden möchten, können Sie das Speichern einer temporären Datei nicht vermeiden, wenn die Größe der hochgeladenen Datei> 500 KB beträgt. Wenn es kleiner als 500 KB ist, wird "BytesIO" verwendet, das den Dateiinhalt im Speicher speichert, und wenn es größer als 500 KB ist, wird der Inhalt in TemporaryFile () gespeichert (wie in der werkzeug-Dokumentation angegeben ). In beiden Fällen wird Ihr Skript blockiert, bis die gesamte hochgeladene Datei empfangen wurde.

Der einfachste Weg, dies zu umgehen, ist:

1) Erstellen Sie Ihre eigene dateiähnliche E / A-Klasse, in der Sie die gesamten eingehenden Daten verarbeiten

2) Überschreiben Sie in Ihrem Skript die Anforderungsklasse mit Ihrer eigenen:

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

3) Ersetzen Sie die request_class von Flask durch Ihre eigene:

app.request_class = MyRequest

4) Geh und trink ein Bier :)


0

Ich habe versucht, genau das Gleiche zu tun, eine Textdatei zu öffnen (eigentlich eine CSV für Pandas). Ich möchte keine Kopie davon erstellen, sondern nur öffnen. Die Form-WTF hat einen schönen Dateibrowser, öffnet dann aber die Datei und erstellt eine temporäre Datei, die sie als Speicherstrom darstellt. Mit ein wenig Arbeit unter der Haube,

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

Ich teile meine Lösung (vorausgesetzt, alles ist bereits für die Verbindung mit Google Bucket in Flask konfiguriert).

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

Mein Post

Direkt zu Google Bucket in der Flasche


-1

Für den Fall, dass wir die In-Memory-Datei auf die Festplatte kopieren möchten. Dieser Code kann verwendet werden

  if isinstanceof(obj,SpooledTemporaryFile):
    obj.rollover()

-1

Wir haben einfach gemacht:

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 Funktion

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

in HTML-Datei

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.