Django download file not working

后端 未结 2 893
臣服心动
臣服心动 2020-12-17 05:32

I\'m trying to make a script for downloading the uploaded files, on the user\'s machine. The problem is that the download simply doesn\'t work (it either downloads me an emp

2条回答
  •  清酒与你
    2020-12-17 06:07

    edited

    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
    

    Why is that:

    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 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)
    

    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> 
    [D:projekty/pracus]|5> type( _ )
                       <5> 
    

    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:\projekty\pracus\ in ()
    
    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
    

    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
    

    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
    

    But that's unnecessary typing.

    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'
    

提交回复
热议问题