luc
luc

Reputation: 43096

Getting an empty file when served by django

I have the following code for managing file download through django.

def serve_file(request, id):

    file = models.X.objects.get(id=id).file #FileField
    file.open('rb')
    wrapper = FileWrapper(file)
    mt = mimetypes.guess_type(file.name)[0]
    response = HttpResponse(wrapper, content_type=mt)

    import unicodedata, os.path
    filename = unicodedata.normalize('NFKD', os.path.basename(file.name)).encode("utf8",'ignore')
    filename = filename.replace(' ', '-') #Avoid browser to ignore any char after the space

    response['Content-Length'] = file.size
    response['Content-Disposition'] = 'attachment; filename={0}'.format(filename)

    #print response
    return response

Unfortunately, my browser get an empty file when downloading.

The printed response seems correct:

Content-Length: 3906
Content-Type: text/plain
Content-Disposition: attachment; filename=toto.txt

blah blah ....

I have similar code running ok. I don't see what can be the problem. Any idea?

PS: I have tested the solution proposed here and get the same behavior

Update: Replacing wrapper = FileWrapper(file) by wrapper = file.read() seems to fix the problem

Update: If I comment the print response, I get similar issue:. the file is empty. Only difference: FF detects a 20bytes size. (the file is bigger than this)

Upvotes: 2

Views: 2208

Answers (2)

Ski
Ski

Reputation: 14487

From django documentation:

FieldFile.open(mode='rb') Behaves like the standard Python open() method and opens the file associated with this instance in the mode specified by mode.

If it works like pythons open then it should return a file-object, and should be used like this:

f = file.open('rb')
wrapper = FileWrapper(f)

Upvotes: 0

Bite code
Bite code

Reputation: 596723

File object is an interable, and a generator. It can be read only once before being exausted. Then you have to make a new one, of use a method to start at the begining of the object again (e.g: seek()).

read() returns a string, which can be read multiple times without any problem, this is why it solves your issue.

So just make sure that if you use a file like object, you don't read it twice in a row. E.G: don't print it, then returns it.

Upvotes: 1

Related Questions