2014-12-23 15 views
14

Sto provando a scrivere una semplice applicazione web con PythonAnywhere e Flask che consente all'utente di caricare un file di testo, genera un file csv, quindi consente all'utente di scaricare il file csv. Non deve essere elegante, deve solo funzionare. Ho già scritto il programma per generare il csv da un file txt sull'unità.Caricamento e download di file con il pallone

In questo momento, la mia funzione apre il file sul disco con:

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

e scrive il csv con:

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

con InputFile e OUTPUTFILE stringhe di essere nomi di file.

Sarebbe meglio per me gestire i file come oggetti, restituiti dal flask/html in qualche modo?

Non so come farlo. Come dovrei strutturare questo programma? Di quanti modelli HTML ho bisogno? Preferirei lavorare sui file senza salvarli da nessuna parte, ma se dovessi salvarli nella directory PythonAnywhere, potrei. Come lo posso fare?

risposta

19

PythonAnywhere dev. Qui. Questa è una buona domanda su Flask e sullo sviluppo web in generale piuttosto che sul nostro sistema, quindi cercherò di dare una risposta generica senza nulla di specifico per noi :-)

Ci sono alcune cose che vorrei ho bisogno di sapere per dare una risposta definitiva alla tua domanda, quindi inizierò elencando le ipotesi che sto facendo - lasciatemi un commento se sbaglio con qualcuno di loro e aggiornerò la risposta in modo appropriato.

  • Suppongo che i file che stai caricando non siano enormi e possano inserirsi in una quantità ragionevole di memoria - diciamo, più piccoli di un megabyte.
  • Suppongo che il programma che hai già scritto per generare il CSV dal file di testo sia in Python e che abbia (o, più probabilmente, potrebbe essere facilmente modificato per avere) una funzione che richiede una stringa contenente i contenuti del file di testo e restituisce i contenuti che devono essere scritti nel CSV.

Se entrambi sono il caso, il modo migliore per strutturare l'app Flask è gestire tutto all'interno di Flask. Un esempio di codice vale più di mille parole, quindi ecco un semplice insieme che consente all'utente di caricare un file di testo, lo esegue attraverso una funzione chiamata transform (che è dove verrà inserita la funzione del tuo programma di conversione - mia sostituisce = con , in tutto il file) e invia i risultati al 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 

quanto riguarda le vostre altre domande:

  • Templates: Non ho usato un modello per questo esempio, perché volevo tutto per adattarsi in un unico pezzo di codice. Se lo facessi correttamente, inserirò le cose generate dalla vista form in un modello, ma questo è tutto.
  • Puoi farlo scrivendo a file - sì, è possibile, e il file caricato può essere salvato utilizzando il nome del file save(metodo) sull'oggetto file che sto utilizzando la proprietà stream di.Ma se i tuoi file sono piuttosto piccoli (come da mia supposizione sopra) allora probabilmente ha più senso elaborarli in memoria come fa il codice sopra.

Spero che tutto sia d'aiuto, e se avete domande, lasciate semplicemente un commento.

+0

Ottima risposta. Cercando di applicare gli elementi qui: http://stackoverflow.com/q/35496045/1389110 – Pyderman

+0

Ho provato la demo di Python ovunque, non funziona, ho ricevuto: Errore interno del server Il server ha rilevato un errore interno ed è stato impossibile completare la richiesta. O il server è sovraccarico o c'è un errore nell'applicazione. – Mostafa

+0

Mi sembra OK ... –

3

meglio aggiungere

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

Se non si aggiunge il tipo di contenuto, FF 48,0 riferito come html e aperto dialogo Salva una volta per HTML e poi per CSV. Se non aggiungi Cache-Control, il risultato potrebbe essere memorizzato nella cache e se pubblichi contenuti attivi questo non è ciò che desideri. Se usi must-revalidate senza età, funzionerà efficacemente come no-cache - vedi here e here per una spiegazione.