2016-05-18 2 views
1

Я пытаюсь выполнить файл .json через эту функцию. Проблема в том, что каждый раз, когда я делаю запрос, браузер отображает содержимое вместо загрузки файла.Обслуживание файла .json для скачивания

Я думаю, это может быть связано с тем, что я использую .read() в качестве параметра для конструктора объектов HttpResponse. Однако, если я использую только объект файла, я получаю следующее исключение:

TypeError: cannot serialize '_io.BufferedRandom' object 

код

try: 
    invoices = models.Invoice.objects.filter(pk__in=document_ids).order_by(*ordering) 
    pcustomers = models.CustomerProxy.objects.all() 
    mixed_query = list(invoices) + list(pcustomers) 

    file = tempfile.NamedTemporaryFile(suffix='.json') 
    file.write(serializers.serialize('json', mixed_query).encode()) 
    file.seek(0) 

    response = HttpResponse(file.read(), content_type='application/json') 
    response['Content-Disposition'] = 'attachment; filename=%s' % file.name 
    response['Content-Length'] = os.path.getsize(file.name) 

except Exception: 
    raise 

return response 

ответ

3

Вам не нужно выполните весь процесс генерации файлов для создания загружаемого файла, вам просто нужно добавить заголовок Content-Disposition обычно. Работает ли код ниже?

+0

Файл сгенерирован, и я вижу его под '/ tmp'. Я просто не могу заставить его быть загруженным файлом вместо содержимого. –

+0

Вам не нужно проходить весь процесс генерации файлов для создания загружаемого файла, вам просто нужно добавить заголовок Content-Disposition. Как это работает, если вы упростите код, удалите всю часть создания файла, как я делаю в коде выше? – raphv

+0

Если я это сделаю, у меня есть тот же результат, что и раньше, это страница, отображаемая как json. –

1

добавить это к ответу Http

HttpResponse(mimetype='application/force-download') 
+0

Это не работает. Я использую Python 3.5, и он говорит, что для этого конструктора нет атрибута mimetype. Возможно, если вы имели в виду 'content_type =" application/force-download "', я пробовал это, и он тоже. –

1

На основе кода, который вы показываете, вам не нужно писать во временный файл. Почему бы вам просто не передать результат serialize() в HttpResponse()?

response = HttpResponse(serializers.serialize('json', mixed_query), content_type='application/json') 

Вы можете установить имя вложения к тому, что вам нравится, что-то описательный, казалось бы, лучше, чем случайный буквенно-цифровой последовательности, порожденной tempfile.NamedTemporaryFile().

response['Content-Disposition'] = 'attachment; filename="invoices_and_customers.json"' 

Если вы действительно хотите, чтобы указать длину:

response['Content-Length'] = len(response.content) 

или вы могли бы добавить ConditionalGetMiddleware промежуточное программное обеспечение для настройки и есть Django добавить Content-Length для вас.

+0

Точно. Мы используем функцию для инкапсуляции запроса и, в конце концов, заменяем заголовок. Я дам ему правильный ответ, так как он может захотеть получить больше очков, когда станет новичком: p. Благодаря! –

+1

Достаточно честный. Также сначала ответил @raphv. – mhawke

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