Файл возврата django через HttpResponse - файл обслуживается некорректно

Я хочу вернуть несколько файлов в HttpResponse и использую следующую функцию. Размер возвращаемого файла всегда равен 1 КБ, и я не знаю почему. Я могу открыть файл, но мне кажется, что он обслуживается некорректно. Поэтому я хотел знать, как можно возвращать файлы с помощью django / python через HttpResponse.

@login_required
def serve_upload_files(request, file_url):
    import os.path
    import mimetypes
    mimetypes.init()

    try:
        file_path = settings.UPLOAD_LOCATION + '/' + file_url
        fsock = open(file_path,"r")
        #file = fsock.read()
        #fsock = open(file_path,"r").read()
        file_name = os.path.basename(file_path)
        file_size = os.path.getsize(file_path)
        print "file size is: " + str(file_size)
        mime_type_guess = mimetypes.guess_type(file_name)
        if mime_type_guess is not None:
            response = HttpResponse(fsock, mimetype=mime_type_guess[0])
        response['Content-Disposition'] = 'attachment; filename=' + file_name            
    except IOError:
        response = HttpResponseNotFound()
    return response

Изменить: ошибка на самом деле не ошибка ;-)

Это решение работает на сервере Apache, поэтому источник в порядке.

При написании этого вопроса я тестировал его локально с сервером разработки django и задавался вопросом, почему он не работает. Мой друг сказал мне, что эта проблема может возникнуть, если на сервере не установлены типы пантомимы. Но он не был уверен, что это проблема. Но одно можно сказать наверняка .. это как-то связано с сервером.


person Thomas Kremmel    schedule 29.03.2010    source источник
comment
Тем, кто пытается использовать этот код, имейте в виду, что аргумент mimetype в HttpResponse был заменен на поле content_type.   -  person Hanan N.    schedule 28.10.2014


Ответы (3)


Попробуйте передать fsock итератор в качестве параметра HttpResponse(), а не его write() метод, который, я думаю, ожидает строку.

response = HttpResponse(fsock, mimetype=...)

См. http://docs.djangoproject.com/en/dev/ref/request-response/#passing-iterators

Кроме того, я не уверен, что вы хотите позвонить close в свой файл перед возвратом response. Поигравшись с этим в оболочке (я не пробовал это в реальном представлении Django), кажется, что response не обращается к файлу, пока не будет прочитан сам response. Попытка прочитать HttpResponse, созданный с использованием закрытого файла, приводит к ValueError: I/O operation on closed file.

Итак, вы можете оставить fsock открытым и позволить сборщику мусора обработать его после того, как ответ будет прочитан.

person Ben James    schedule 29.03.2010
comment
Привет, спасибо за ответ. К сожалению это ничего не меняет. ответ = HttpResponse (fsock, mimetype = mime_type_guess [0]). Файл по-прежнему обслуживается некорректно. Кроме того, я проверил размер файла (с file_size = os.path.getsize (file_path) размер файла печати: + str (file_size)), прежде чем я верну его через HttpResponse, и он вернет: размер файла: 56349. Таким образом, файл правильно считывается из файловой системы, и что-то пошло не так при его возврате. - person Thomas Kremmel; 29.03.2010
comment
Том Том, смотри дополнения к моему ответу. - person Ben James; 29.03.2010
comment
Я согласен с Беном. Когда fsock добавляется к HttpResponse либо в конструкторе, либо с помощью метода write, он добавляется во внутренний стек содержимого, поддерживаемый HttpResponse. Этот стек не оценивается позже, в последний возможный момент, когда ответ действительно необходим. Вам нужно оставить fsock открытым, иначе HttpResponse вызовет ошибку при попытке чтения из него. Сборщик мусора позаботится о закрытии файла. - person Jarret Hardie; 29.03.2010
comment
Хорошо спасибо. Я оставил fsock открытым и больше не вижу сообщения об ошибке. Но размер файла все равно 1кб :( - person Thomas Kremmel; 29.03.2010
comment
Если вы изменили код, не могли бы вы обновить свой вопрос, чтобы отразить его? Я мог бы упомянуть еще кое-что, но, возможно, это станет неактуальным, если вы сейчас существенно измените код. - person Ben James; 29.03.2010

Может ли быть, что файл содержит некоторые символы, отличные от ascii, которые нормально отображаются в производстве, но не в разработке?

Попробуйте прочитать файл как двоичный:

fsock = open(file_path,"rb")
person alves    schedule 20.01.2011
comment
Ты мой спаситель! Все основные сообщения об обслуживании файлов через Django не охватывают эту необходимость в двоичном коде при обслуживании из Windows. Кстати, установка rb работает при использовании FileWrapper для обслуживания чанков через: return HttpResponse (FileWrapper (open (filename, rb)), content_type = mimetypes.guess_type (filename) [0]) - person garromark; 03.04.2012

Попробуйте отключить "django.middleware.gzip.GZipMiddleware" из MIDDLEWARE_CLASSES в settings.py

У меня была та же проблема, и после того, как я просмотрел папку промежуточного программного обеспечения, это промежуточное программное обеспечение показалось мне виноватым, и его удаление помогло мне.

person Anonymous    schedule 28.02.2012