Using HttpResponse as a file - 'HttpResponse' object has no attribute 'seek' error

1,929 views
Skip to first unread message

kip

unread,
Feb 21, 2008, 6:41:55 AM2/21/08
to Django users
I thought I would be able to use an HttpResponse object as the file
argument for ZipFile, like this:

response = HttpResponse(mimetype='application/zip')
response['Content-Disposition'] = 'attachment; filename=zipfile.zip'
file = zipfile.ZipFile(response, "w")

but as soon as I try to write to it I get the error "'HttpResponse'
object has no attribute 'seek'".

Am I missing something here?

Thanks,

Kip.

Malcolm Tredinnick

unread,
Feb 21, 2008, 7:01:20 AM2/21/08
to django...@googlegroups.com

No, you have all the information that's required to diagnose what you're
doing wrong. ZipFile apparently expects something with a seek() method
and HttpResponse doesn't have one (since it outputs content in a linear
fashion). You also cannot use HttpResponse as a lawn mower or an a
floatation device as it's similarly not appropriate.

An HttpResponse is something that is designed to produce a string. That
string is sent back to the user. Since ZipFile wants something that acts
as a file, you need to turn the HttpResponse into something like that.
Try using StringIO.

Regards,
Malcolm

--
I just got lost in thought. It was unfamiliar territory.
http://www.pointy-stick.com/blog/

Ned Batchelder

unread,
Feb 21, 2008, 7:34:54 AM2/21/08
to django...@googlegroups.com
In Python, there is a loose concept of a "file-like" object.  This means that the object behaves like a file under duck-typing, meaning it has the right methods to be treated just as if it were a file.  But the concept is only loosely defined, and different file-like objects implement different numbers of methods, according to their abilities.  HttpResponse does not implement seek(), and many consumers of file-like objects don't ever call seek(), so HttpResponses can be used as files in many cases.  ZipFile seems to be one case where it cannot, because ZipFile calls seek().

Both the HttpRequest docs (http://www.djangoproject.com/documentation/request_response/) and the Python file docs (http://docs.python.org/lib/bltin-file-objects.html) mention "file-like" obliquely, with reference to methods that are or are not, or may or may not, be implemented.

As Malcolm points out, seek() would require buffering, which you can provide by using an intermediary like StringIO.

--Ned.
http://nedbatchelder.com/blog
-- 
Ned Batchelder, http://nedbatchelder.com

kip

unread,
Feb 21, 2008, 8:36:36 AM2/21/08
to Django users
Thanks Ned, I had misunderstood the concept of "file-like" and you've
explained it admirably, exactly what I needed to know. Though
Malcolm's tip regarding the unsuitability of HttpResponse as a
flotation device will be a life-saver for many, I'm sure.

This is what works for me:

import cStringIO, zipfile

response = HttpResponse(mimetype='application/zip')
response['Content-Disposition'] = 'attachment; filename=zipfile.zip'
fobj = cStringIO.StringIO()
f = zipfile.ZipFile(fobj, "w")
f.write(filename)
f.close()
zip = fobj.getvalue()
fobj.close()
response.write(zip)
return response


On Feb 21, 12:34 pm, Ned Batchelder <n...@nedbatchelder.com> wrote:
> In Python, there is a loose concept of a "file-like" object.  This means
> that the object behaves like a file under duck-typing, meaning it has
> the right methods to be treated just as if it were a file.  But the
> concept is only loosely defined, and different file-like objects
> implement different numbers of methods, according to their abilities.  
> HttpResponse does not implement seek(), and many consumers of file-like
> objects don't ever call seek(), so HttpResponses can be used as files in
> many cases.  ZipFile seems to be one case where it cannot, because
> ZipFile calls seek().
>
> Both the HttpRequest docs
> (http://www.djangoproject.com/documentation/request_response/) and the
> Python file docs (http://docs.python.org/lib/bltin-file-objects.html)
> mention "file-like" obliquely, with reference to methods that are or are
> not, or may or may not, be implemented.
>
> As Malcolm points out, seek() would require buffering, which you can
> provide by using an intermediary like StringIO.
>
> --Ned.http://nedbatchelder.com/blog
Reply all
Reply to author
Forward
0 new messages