2010-03-17 3 views
7

Я пытаюсь загрузить файл CSV с помощью HttpResponse, чтобы убедиться, что браузер рассматривает его как вложение. Я следую приведенным инструкциям here, но мой браузер не запрашивает диалоговое окно «Сохранить как». Я не могу понять, что не так с моей функцией. Вся помощь приветствуется.Загрузка файла csv в 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) 

Happy Pat's day!

ответ

1

Спасибо всем за ваши предложения. Я выбрал несколько новых трюков :) Однако я думаю, что нашел ответ на мою проблему здесь: Downloading CSV via AJAX Моя функция «savefile» вызывается с помощью запроса Ajax, и кажется, что ajax имеет ограничение, где «сохранить как диалоговое окно» msgstr "не отображается независимо от заголовков HTTP.

Я должен был упомянуть, что я использую Ajax для вызова этой функции, но мне никогда не приходило в голову, что это может быть проблемой. :) Thankyou StackOverflow!

5

Вы попробовали указать тип содержимого? , например.

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

Edit:

Обратите внимание, этот код успешно запускает "Сохранить как" диалог для меня. Примечание. Я указываю «application/x-download» непосредственно в аргументе mimetype. Вы также можете перепроверить свой код и убедиться, что ваш путь к файлу верен, и что FileWrapper() не делает что-то странное.

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

попробовал, все еще не работает. Я вижу ответ и заголовки в FireBug, но я не получаю диалоговое окно. – spyder

+0

Попробуйте мое текущее редактирование. – Cerin

+0

Я пробовал, но не работал. Пожалуйста, см. Мой ответ, я узнал, что проблема не имеет ничего общего с django. Спасибо – spyder

7

Если файл статический (т.е. не создаются специально для этого запроса) вы не должны служить его через Джанго в любом случае. Вы должны настроить некоторый путь (например,/static /), который будет обслуживаться вашим веб-сервером, и сохранить все служебные данные django.

Если файл динамический, есть 2 варианта:

  1. Создайте его в памяти и служат его от Джанго.
  2. Создайте его на диске и верните ему HttpResponseRedirect, чтобы ваш веб-сервер имел дело с самой загрузкой (если файл очень большой, вы должны использовать этот параметр).

Как для обслуживания динамически, я использую следующий код (который является упрощенной версией 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) 

Чтобы использовать его, просто использовать обратный CSVResponse (...) прохождение в списке списков, список dicts (с теми же ключами), QuerySet, ValuesQuerySet

+0

Он генерируется «на ходу» для «этого» запроса и временно хранится под/static /. – spyder

+0

Отредактировано после вашего комментария. –

+0

Благодарим вас за подробности. ! – spyder

0

Не имеет значения, если вы не вставляете имя файла в двойные кавычки? Пример кода не указывает имя файла:

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

но делает ваш код:

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

Спасибо, попробовал ... не радость. – spyder

0

Thomas, я использовал функцию Ajax для сохранения и скачивания этого файла.Похоже, что в таком случае поле «Сохранить как» не будет отображаться независимо от заголовков. Я просто использовал javascript для загрузки этого файла. window.open («путь/в/файл»); и он делает трюк. Я тестировал на IE6 и Firefox, и появляется диалоговое окно.

Смежные вопросы