Why render to a temp file? Why not simply render to a byte array like ScreenFopViewHandler (pdf)
does? Temp files need cleaning up.
The best way I can think of now is to have a generic ByteArrayViewHandler or similar, that outputs
any arbitrary byte array to the browser (via HttpServletResponse).
Don't render to a byte array nor a temp file, actually, because that will take up space. Instead,
do the following.
In <request-map>, have an <event> that will create an object that extends an interface say
GenericFileRenderer with at least a method like GenericFileRenderer.render(SomeContentPassedIn,
SomeOutputStream). For a somewhat analogous example, see ScreenFopViewHandler doing
"screens.render(page)".
The GenericFileRenderer object will be somehow passed to the ByteArrayViewHandler (in a
<view-map>), where a line like "renderer.render(content, outputStream)" will do the actual
rendering and outputting. It's a callback mechanism, where ByteArrayViewHandler "callback" our
special renderer (with standard interface GenericFileRenderer).
Well, the ScreenFopViewHandler is not a good example here, since it stores the rendered content
(could be large) in a StringWriter. But the idea I'm trying to put across is to perform the
rendering only *at the point of output*, so we won't be storing megabytes of data in memory or
temp files.
In effect, we will be able to output just about any byte content to the browser. The simplest
renderer could just "write out" a string, which might give us a content type of "text/plain". Any
number of renderer types could be created to handle zip, tar, bz2, whatever (it's a "plug-in"
architecture). In fact, even the ScreenFopViewHandler could be refactored to use this "render only
during output" method (later on).
If there *really* is a need for this, let me know. I'm feeling like I need a stretch, and may
implement this just for fun.
Jonathon
Adrian Crum wrote:
Chris,
I'm not sure what the proper solution would be. Your case is very
similar to the one I faced while refactoring the FOP rendering - that's
why I was thinking a generic file view handler would be handy. It would
work something like this:
Render the specified screen to a temp file
Branch to a conversion routine (temp file as arg) based on content type
Conversion routine returns converted file
Copy converted file to response OutputStream
Conversion routines could handle FOP, Zip, or any other file format that
comes along.
-Adrian
Chris Howe wrote:
Thanks for your help Adrian! That helped me track down a workaround
(big smile). in ScreenWidgetViewHandler.java#render(..,..,..,...,.)
there is the section
if (useOutputStreamNotWriter) {
ServletOutputStream ros = response.getOutputStream();
writer = new OutputStreamWriter(ros, "UTF-8");
} else {
writer = response.getWriter();
}
I set useOutputStreamNotWriter to true based on the content type.
What should be the proper solution that can be put back into the
community project? Another ViewHandler or just additional flags to
change whether .getWriter() or getOutputStream() is used?
----- Original Message ----
From: Adrian Crum <[EMAIL PROTECTED]>
To: [email protected]
Sent: Wednesday, November 21, 2007 10:16:39 AM
Subject: Re: Write to Browser
You'll have to back up in the code some and see how the writer is being
used. If nothing has been written already, then you can copy the
InputStream to the Writer.
If your code is being called from the screen widget, then things get
tricky - since it has probably already sent out HTML text to the
browser.
It would be handy to have a generic view handler for this kind of
scenario.
Chris Howe wrote:
It won't let me do response.getOutputStream. I get an error that
says "getWriter() has already been called for this response"
----- Original Message ----
From: Adrian Crum <[EMAIL PROTECTED]>
To: [email protected]
Sent: Wednesday, November 21, 2007 9:45:47 AM
Subject: Re: Write to Browser
FileInputStream zipInStream = new FileInputStream(zipFile);
OutputStream browserOutStream = response.getOutputStream();
response.setContentLength((int)zipFile.length());
response.setContentType("application/zip");
// Call a routine to copy bytes from zipInStream to browserOutStream
-Adrian
Chris Howe wrote:
I'm trying to create a zip file on the fly. I've created it properly
so that it will write to the file system, but I would prefer to
write
to the browser so that the user can download it. This seems like it
should be so simple, but I'm missing it. TIA for any help!
Chris