2014-12-23 4 views
14

Ich versuche eine wirklich einfache Webapp mit PythonAnywhere und Flask zu schreiben, mit der der Benutzer eine Textdatei hochladen kann, eine CSV-Datei generiert und den Benutzer dann die CSV-Datei herunterladen lässt. Es muss nicht schick sein, es muss nur funktionieren. Ich habe bereits das Programm zum Erzeugen der CSV aus einer TXT-Datei auf dem Laufwerk geschrieben.Hochladen und Herunterladen von Dateien mit Flask

Gerade jetzt, öffnet meine Funktion, um die Datei auf dem Laufwerk mit:

with open(INPUTFILE, "r") as fname: 

und schreibt die csv mit:

with open(OUTPUTFILE, 'w') as fname: 

mit INPUTFILE und OUTPUT sind Dateinamen-Strings.

Wäre es für mich besser, die Dateien als Objekte zu behandeln, die irgendwie vom flask/html zurückgegeben werden?

Ich weiß nicht, wie dies zu tun. Wie soll ich dieses Programm strukturieren? Wie viele HTML-Templates brauche ich? Ich würde lieber an den Dateien arbeiten, ohne sie irgendwo zu speichern, aber wenn ich sie im PythonAnywhere-Verzeichnis speichern müsste, könnte ich. Wie kann ich das machen?

Antwort

19

PythonAnywhere Dev hier. Dies ist eine gute Frage über Flask und Web-Entwicklung im Allgemeinen eher als spezifisch für unser System, also werde ich versuchen, eine generische Antwort ohne etwas spezifisch für uns zu geben :-)

Es gibt ein paar Dinge, die ich würde müssen Sie wissen, um eine definitive Antwort auf Ihre Frage zu geben, also werde ich mit der Auflistung der Annahmen beginnen, die ich mache - lassen Sie mich einen Kommentar, wenn ich falsch mit ihnen bin und ich werde die Antwort entsprechend aktualisieren.

  • Ich gehe davon aus, dass die hochgeladenen Dateien nicht riesig sind und in eine vernünftige Menge an Speicher passen - sagen wir mal kleiner als ein Megabyte.
  • Ich gehe davon aus, dass das Programm, das Sie bereits geschrieben haben, um die CSV aus der Textdatei zu generieren, in Python ist, und dass es eine Funktion hat (oder vielleicht eher leicht geändert werden kann) eine Zeichenfolge, die den Inhalt der Textdatei enthält, und gibt den Inhalt zurück, der in die CSV-Datei geschrieben werden muss.
  • Wenn beides der Fall ist, dann wäre der beste Weg, um Ihre Flask App zu strukturieren, alles in Flask zu behandeln. Ein Codebeispiel sagt mehr als tausend Worte, also ist hier ein einfaches, das ich zusammensetze, das dem Benutzer erlaubt, eine Textdatei hochzuladen, führt es durch eine Funktion, die transform genannt wird (wo die Funktion von Ihrem Umwandlungsprogramm einstecken würde) ersetzt einfach = durch , in der Datei) und sendet die Ergebnisse zurück an den Browser. There's a live version of this app on PythonAnywhere here.

    from flask import Flask, make_response, request 
    
    app = Flask(__name__) 
    
    def transform(text_file_contents): 
        return text_file_contents.replace("=", ",") 
    
    
    @app.route('/') 
    def form(): 
        return """ 
         <html> 
          <body> 
           <h1>Transform a file demo</h1> 
    
           <form action="/transform" method="post" enctype="multipart/form-data"> 
            <input type="file" name="data_file" /> 
            <input type="submit" /> 
           </form> 
          </body> 
         </html> 
        """ 
    
    @app.route('/transform', methods=["POST"]) 
    def transform_view(): 
        file = request.files['data_file'] 
        if not file: 
         return "No file" 
    
        file_contents = file.stream.read().decode("utf-8") 
    
        result = transform(file_contents) 
    
        response = make_response(result) 
        response.headers["Content-Disposition"] = "attachment; filename=result.csv" 
        return response 
    

    In Bezug auf Ihre Fragen:

    • Vorlagen: ich keine Vorlage für dieses Beispiel verwendet haben, weil ich alles passen zu einem einzigen Stück Code wollte. Wenn ich es richtig mache, dann würde ich die Sachen, die von der form Ansicht generiert werden, in eine Vorlage einfügen, aber das ist alles.
    • Können Sie es tun, indem Sie auf Dateien zu schreiben - ja Sie können, und die hochgeladene Datei kann mithilfe der save(Dateinamen) Methode auf das file Objekt gespeichert werden, die ich bin mit der stream Eigenschaft.Aber wenn Ihre Dateien ziemlich klein sind (gemäß meiner Annahme oben), dann ist es wahrscheinlich sinnvoller, sie wie der obige Code im Speicher zu verarbeiten.

    Ich hoffe, dass alle hilft, und wenn Sie Fragen haben, dann hinterlassen Sie einfach einen Kommentar.

    +0

    Große Antwort. Der Versuch, hier Elemente davon anzuwenden: http://stackoverflow.com/q/35496045/1389110 – Pyderman

    +0

    ich den Python überall Demo versucht, es nicht funktioniert, habe ich: Internal Server Error Der Server hat einen internen Fehler festgestellt und war Ich kann Ihre Anfrage nicht abschließen. Entweder ist der Server überlastet oder es liegt ein Fehler in der Anwendung vor. – Mostafa

    +0

    Sieht OK für mich aus ... –

    3

    Bessere

    response.headers["Cache-Control"] = "must-revalidate" 
    response.headers["Pragma"] = "must-revalidate" 
    response.headers["Content-type"] = "application/csv" 
    

    hinzufügen Wenn Sie den Inhaltstyp nicht fügen, FF 48,0 berichtet es als HTML und einmal geöffnet Speichern-Dialog für HTML und dann für CSV. Wenn Sie Cache-Control nicht hinzufügen, wird das Ergebnis möglicherweise zwischengespeichert, und wenn Sie aktive Inhalte bereitstellen, ist dies nicht das, was Sie möchten. Wenn Sie must-revalidate ohne Alter verwenden, dient es effektiv als No-Cache - siehe here und here für eine Erklärung.