This is a followup from the Webware-discuss list (see Has anyone tried to stream a reportlab)
The Content Disposition Header is defined in RFC 2183. Its purpose (among others) is to give a hint about the name of the following content. This is quite useful, when one tries to pipe a file to the browser. Without this header, the browser will show the scriptname, instead of the filename, when trying to use the Save as function.
The following code should run right away as a servlet. It shows the content of some directory and lets you download its files. It is tested with Webware (10 day old CVS), OneShot.cgi Adapter and the following browsers. The following list gives you an idea, what browsers will show the right filename (or not):
Opera on Linux (works)
Konqueror (doesn't work)
Mozilla 0.96 on Linux (doesn't work, though it should according to documentation) IE5 should work.
---
from WebKit.Page import Page import os, mimetypes FILEDIR = "/path/to/directory" class Main(Page): def title(self): return 'Webware Download Test Page' def writeBody(self): response = self.response() request = self.request() adapterName = request.adapterName() if request.hasField('file'): filename = '%s/%s' % (FILEDIR,request.field('file')) (mtype,enctype) = mimetypes.guess_type(filename) fd = open(filename) response.setHeader('Content-Type',mtype) response.setHeader('Content-Disposition','attachment; filename="%s"' % request.field('file')) response.flush() chunksize = response.streamOut().bufferSize() outchunk = fd.read(chunksize) while outchunk: self.write(outchunk) outchunk = fd.read(chunksize) else: files = os.listdir(FILEDIR) self.writeln('<h1>Webware Download Test</h1>') self.writeln('<ul>') for file in files: self.writeln('<li><a href="%s/Test/Main.py?file=%s">%s</a>' % (adapterName,file,file)) self.writeln('</ul>')
---
I'm not entirely sure if this code is really streaming the file or if the Webware outStream is buffering. I think that "response.flush()" will disable buffering, but I'm not sure.
Please comment and feel free to put more elegant versions in place. Maybe we should start a UsefullRfcs page.
-- StephanDiehl - 14 Nov 2001
As far as the buffering goes, by calling response.flush(), you tell webware to go ahead and send what you have written to the stream so far. By default, the outStream waits until you are done writting to send anything, calling flush allows you to send data as it becomes available.
-- JayLove - 27 Dec 2001
It seems to me that the above code is not correct because the streamed content consists not only of the contents of the intended file but also the html headers, which are not desired. To solve this I override writeHTML like this:
def writeHTML(self): if self.request().hasField('file'): self.writeBody() else: Page.writeHTML(self)
-- RubenMendes - 4 Oct 2004