Django скачать файл не работает - PullRequest
2 голосов
/ 09 июля 2010

Я пытаюсь создать скрипт для загрузки загруженных файлов на компьютер пользователя. Проблема в том, что загрузка просто не работает (она либо загружает мне пустой файл, либо выдает ошибки).

последняя ошибка: приведение к Unicode: нужна строка или буфер, FieldFile найден

def download_course(request, id):
    course = Courses.objects.get(pk = id).course

    path_to_file = 'root/cFolder'
    filename = course # Select your file here.                                
    wrapper = FileWrapper(file(course))
    content_type = mimetypes.guess_type(filename)[0]
    response = HttpResponse(wrapper, content_type = content_type)
    response['Content-Length'] = os.path.getsize(filename)
    response['Content-Disposition'] = 'attachment; filename=%s/' % smart_str(course)

    return response

как я могу правильно объявить имя файла, чтобы он каждый раз знал, какой файл загружать: имя файла на самом деле 'course', как указано выше

Спасибо!

Ответы [ 2 ]

5 голосов
/ 09 июля 2010

изм

Я думаю, что вам нужно извлечь path значение из объекта FileField:

def download_course(request, id):
    course = Courses.objects.get(pk = id).course

    path = course.path # Get file path
    wrapper = FileWrapper( open( path, "r" ) )
    content_type = mimetypes.guess_type( path )[0]

    response = HttpResponse(wrapper, content_type = content_type)
    response['Content-Length'] = os.path.getsize( path ) # not FileField instance
    response['Content-Disposition'] = 'attachment; filename=%s/' % \ 
                                       smart_str( os.path.basename( path ) ) # same here

    return response

Почему это так:

Допустим, у меня есть (ну, у меня на самом деле) Модель:

class DanePracodawcy( DaneAdresowe, DaneKontaktowe ):
    # other fields
    logo = ImageWithThumbnailsField( upload_to = 'upload/logos/',
                                  thumbnail = {'size': (180, 90)},
                                  blank = True )

ImageWithThumbnailsField является подклассом FileField, поэтому он ведет себя так же. Теперь, когда я делаю SELECT:

mysql> select logo from accounts_danepracodawcy;
+-----------------------------+
| logo                        |
+-----------------------------+
| upload/logos/Lighthouse.jpg |
+-----------------------------+
1 row in set (0.00 sec)

показывает (относительно MEDIA_ROOT) путь к сохраненному файлу. Но когда я получаю доступ к logo Атрибут модели:

[D:projekty/pracus]|1> from accounts.models import DanePracodawcy
[D:projekty/pracus]|4> DanePracodawcy.objects.get().logo
                   <4> <ImageWithThumbnailsFieldFile: upload/logos/Lighthouse.jpg>
[D:projekty/pracus]|5> type( _ )
                   <5> <class 'sorl.thumbnail.fields.ImageWithThumbnailsFieldFile'>

Я получаю экземпляр какого-то объекта. Если я попытаюсь передать этот экземпляр os.path.getsize:

[D:projekty/pracus]|8> import os.path
[D:projekty/pracus]|9> os.path.getsize( DanePracodawcy.objects.get().logo )
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

D:\projekty\pracus\<ipython console> in <module>()

C:\Python26\lib\genericpath.pyc in getsize(filename)
     47 def getsize(filename):
     48     """Return the size of a file, reported by os.stat()."""
---> 49     return os.stat(filename).st_size
     50
     51

TypeError: coercing to Unicode: need string or buffer, ImageWithThumbnailsFieldFile found

Я получаю TypeError, как и вы. Поэтому мне нужен путь к файлу в виде строки, которую можно получить с помощью атрибута path:

[D:projekty/pracus]|13> os.path.getsize(  DanePracodawcy.objects.get().logo.path )
                   <13> 561276L

В качестве альтернативы, я мог бы получить атрибут name и os.path.join его с установкой MEDIA_ROOT:

[D:projekty/pracus]|11> from django.conf import settings
[D:projekty/pracus]|12> os.path.getsize(  os.path.join( settings.MEDIA_ROOT, DanePracodawcy.objects.get().logo.name ) )
                   <12> 561276L

Но это ненужное печатание.

Последнее, что следует отметить: поскольку path является абсолютным путем, мне нужно извлечь имя файла, чтобы передать его в заголовок Content-Disposition:

[D:projekty/pracus]|16> DanePracodawcy.objects.get().logo.path
                   <16> u'd:\\projekty\\pracus\\site_media\\upload\\logos\\lighthouse.jpg'
[D:projekty/pracus]|17> os.path.basename( DanePracodawcy.objects.get().logo.path )
                   <17> u'lighthouse.jpg'
2 голосов
/ 09 июля 2010

Если вы не разрешаете пользователю загружать динамически сгенерированный файл, я не понимаю, зачем вам все это делать.

Вы можете просто позволить этому представлению перенаправить на соответствующий путь, и соответствующие заголовки устанавливаются сервером, обслуживающим статические файлы; обычно apache или nginx

Я бы сделал это следующим образом:

from django.conf import settings

def download_course(request,id):
    course = get_object_or_404(Course,id=id)
    filename = course.course
    return redirect('%s/%s'%(settings.MEDIA_URL,filename))

Наслаждайтесь:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...