2010-03-17 1 views
7

Sto cercando di scaricare un file CSV utilizzando HttpResponse per assicurarmi che il browser lo tratti come allegato. Seguo le istruzioni fornite here ma il mio browser non richiede una finestra di dialogo "Salva con nome". Non riesco a capire cosa c'è di sbagliato nella mia funzione. Tutto l'aiuto è apprezzato.Download di un file CSV in django

 
    dev savefile(request): 
     try: 
      myfile = request.GET['filename'] 
      filepath = settings.MEDIA_ROOT + 'results/' 
      destpath = os.path.join(filepath, myfile) 
      response = HttpResponse(FileWrapper(file(destpath)), mimetype='text/csv') 
      response['Content-Disposition'] = 'attachment; filename="%s"' %(myfile) 
      return response 
     except Exception, err: 
      errmsg = "%s"%(err) 
      return HttpResponse(errmsg) 

Felice giorno di Pat!

risposta

1

Grazie a tutti per i vostri suggerimenti. Ho scelto alcuni nuovi trucchi :) Comunque penso di aver trovato la risposta al mio problema qui: Downloading CSV via AJAX La mia funzione "savefile" viene chiamata tramite una richiesta Ajax e sembra che ajax abbia una limitazione dove "salva come finestra di dialogo "non appare a prescindere dalle intestazioni HTTP.

Avrei dovuto dire che uso Ajax per chiamare questa funzione ma non mi è mai venuto in mente che questo potrebbe essere un problema :) Grazie StackOverflow!

5

Hai provato a specificare il tipo di contenuto? ad es.

response['Content-Type'] = 'application/x-download'; 

Edit:

nota, questo codice innesca con successo un "Salva con nome" finestra di dialogo per me. Nota Specifico "application/x-download" direttamente nell'argomento mimetype. Potresti anche voler ricontrollare il tuo codice e assicurarti che il percorso del file sia corretto e che FileWrapper() non stia facendo qualcosa di strano.

def save_file(request): 
    data = open(os.path.join(settings.PROJECT_PATH,'data/table.csv'),'r').read() 
    resp = django.http.HttpResponse(data, mimetype='application/x-download') 
    resp['Content-Disposition'] = 'attachment;filename=table.csv' 
    return resp 
+0

provato, non funziona ancora. Posso vedere la risposta e le intestazioni in FireBug ma non ottengo una finestra di dialogo. – spyder

+0

Prova la mia modifica attuale. – Cerin

+0

L'ho provato ma non ha funzionato. Per favore vedi la mia risposta, ho scoperto che il problema non ha nulla a che fare con Django. Grazie – spyder

7

Se il file è statica (non cioè generato appositamente per questa richiesta) non dovrebbe essere servendo attraverso Django comunque. Dovresti configurare un percorso (come/static /) per essere servito dal tuo webserver e salvare tutto il sovraccarico di django.

Se il file è dinamica, ci sono 2 opzioni:

  1. crearlo in memoria e servite da Django.
  2. Crealo sul disco e restituisci un HttpResponseRedirect, in modo che il tuo server web si occupi del download stesso (se il file è molto grande, dovresti usare questa opzione).

quanto per servire in modo dinamico, ho usato il seguente codice (che è una versione semplificata del ExcelResponse)

import StringIO 
from django.db.models.query import ValuesQuerySet, QuerySet 

class CSVResponse(HttpResponse): 

    def __init__(self, data, output_name='data', headers=None, encoding='utf8'): 

    # Make sure we've got the right type of data to work with 
    valid_data = False 
    if isinstance(data, ValuesQuerySet): 
     data = list(data) 
    elif isinstance(data, QuerySet): 
     data = list(data.values()) 
    if hasattr(data, '__getitem__'): 
     if isinstance(data[0], dict): 
      if headers is None: 
       headers = data[0].keys() 
      data = [[row[col] for col in headers] for row in data] 
      data.insert(0, headers) 
     if hasattr(data[0], '__getitem__'): 
      valid_data = True 
    assert valid_data is True, "CSVResponse requires a sequence of sequences" 

    output = StringIO.StringIO() 
    for row in data: 
     out_row = [] 
     for value in row: 
      if not isinstance(value, basestring): 
       value = unicode(value) 
      value = value.encode(encoding) 
      out_row.append(value.replace('"', '""')) 
     output.write('"%s"\n' % 
        '","'.join(out_row))    
    mimetype = 'text/csv' 
    file_ext = 'csv' 
    output.seek(0) 
    super(CSVResponse, self).__init__(content=output.getvalue(), 
             mimetype=mimetype) 
    self['Content-Disposition'] = 'attachment;filename="%s.%s"' % \ 
     (output_name.replace('"', '\"'), file_ext) 

Per usarlo, basta usare CSVResponse ritorno (...) che passa in un elenco di elenchi, un elenco di dict (con le stesse chiavi), un QuerySet, un ValuesQuerySet

+0

E 'generato al volo per "questa" richiesta e memorizzato temporaneamente sotto/statico /. – spyder

+0

Modificato dopo il tuo commento –

+0

Grazie per i dettagli ! – spyder

0

Fa alcuna differenza se non si racchiude il nome del file tra virgolette? Il codice di esempio non cita il nome del file:

response['Content-Disposition'] = 'attachment; filename=foo.xls' 

ma il codice fa:

response['Content-Disposition'] = 'attachment; filename="foo.xls"' 
+0

Grazie, provato ... non c'è gioia. – spyder

0

Thomas, Avevo utilizzato una funzione Ajax per salvare e scaricare questo file.Sembra che in tal caso la casella "Salva come" non apparirà a prescindere dalle intestazioni. Ho semplicemente usato javascript per scaricare quel file. window.open ("percorso/su/file"); e fa il trucco. Ho provato su IE6 e Firefox e appare la finestra di dialogo.