Many of you have probably noticed that sometimes on the internet when
you click on a link, a "Download File" dialog box appears without the
page refreshing. You may even know that this is a special feature of
HTTP that allows for attachments. This is also how most sites do
"automatic downloads".
Like I said this is an HTTP feature. All you have to do is set the
"Content-Type" header to "application/x-download" and the
"Content-Disposition" header to indicate an attachment.
As an example, let's say you have a database and you want to allow
people to download one of the tables as a .csv file. Here's an example
TurboGears controller that uses this HTTP feature along with the new
csvexport functionality from SQLObject. Look how few lines of code
this is! This is why I'm such a TurboGears fanatic:
@expose()
def export_addressbook(self):
from sqlobject.util.csvexport import export_csv
cherrypy.response.headers['Content-Type'] =
"application/x-download"
cherrypy.response.headers['Content-Disposition'] = 'attachment;
filename="Addresses.csv"'
for line in export_csv(Address).readlines():
yield line
Note 1: You'll need a *really* recent version of SQLObject to use this.
Note 2: I haven't tested this, but I've tested similar code. It should
work (TM).
Note 3: If your table is really big, you wouldn't do it this way,
because it would have to create a copy of the entire table in memory.
In that situation, I would create a custom version of SQLObject's
"export_csv" function that yielded the results immediately to cherrypy
instead of using the StringIO intermediary.
Indeed. CherryPy 3 has a helper for this in lib/static:
def serve_download(path, name=None):
"""Serve 'path' as an application/x-download attachment."""
# This is such a common idiom I felt it deserved its own wrapper.
return serve_file(path, "application/x-download", "attachment",
name)
Robert Brewer
System Architect
Amor Ministries
fuma...@amor.org