且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Django下载文件不起作用

更新时间:2023-10-17 17:32:28

已编辑

我认为您需要从 FileField 对象中提取 path 值:

I think that you need to extract path value from FileField object:

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

这是为什么:

假设我有(好吧,我实际上有)模型:

Let's say I have (well, I actually have) Model:

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

ImageWithThumbnailsField 是 FileField 的子类,所以它的行为方式相同.现在,当我做 SELECT 时:

ImageWithThumbnailsField is subclass of FileField, so it behaves the same way. Now, when I do SELECT:

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

它显示(相对于 MEDIA_ROOT)存储文件的路径.但是当我访问 logo 模型属性时:

it shows (relative to MEDIA_ROOT) path of stored file. But when I access logo Model attribute:

[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:

I get instance of some object. If I try to pass that instance to 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:projektypracus<ipython console> in <module>()

C:Python26libgenericpath.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 属性获取:

I get TypeError, like you. So I need file path as string, which can be obtained with path attribute:

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

或者,我可以通过 MEDIA_ROOT 设置获取 name 属性和 os.path.join 它:

Alternatively, I could get name attribute and os.path.join it with MEDIA_ROOT setting:

[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 标头:

Last thing to note: because path is absolute path, I need to extract filename to pass it to Content-Disposition header:

[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'