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
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> <ImageWithThumbnailsFieldFile: upload/logos/Lighthouse.jpg>
[D:projekty/pracus]|5> type( _ )
<5> <class 'sorl.thumbnail.fields.ImageWithThumbnailsFieldFile'>
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\<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
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'
Unless you are letting the user download a dynamically generated file, I don't see why you need to do all that.
You can just let this view redirect to the appropriate path, and the respective headers are set by the server serving the static files; typically apache or nginx
I'd do your this view as follows:
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))
Enjoy :)