Permalink
Browse files

Fixed StreamingResponse section

Closes #42

You have to know the length before sending
  • Loading branch information...
1 parent 2cd66ed commit 41fcc7cd3dc8ba6fdfe9f32cab34029b0705d425 @dchenbecker dchenbecker committed Feb 1, 2011
Showing with 51 additions and 47 deletions.
  1. +51 −47 chap-advanced.lyx
View
@@ -1398,9 +1398,17 @@ InMemoryResponse
\end_layout
\begin_layout Standard
-The InMemoryResponse allows you to return an array of bytes directly to
- the user along with a set of HTTP headers, cookies and a response code.
- An example of using InMemoryResponse was given in section
+The
+\family typewriter
+InMemoryResponse
+\family default
+ allows you to return an array of bytes directly to the user along with
+ a set of HTTP headers, cookies and a response code.
+ An example of using
+\family typewriter
+InMemoryResponse
+\family default
+ was given in section
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:Custom-dispatch-func"
@@ -1420,10 +1428,20 @@ StreamingResponse
\end_layout
\begin_layout Standard
-The StreamingResponse class is similar to the InMemoryResponse, except that
- instead of reading from a buffer, it reads from an input object.
- The input object is not required to be a subclass of java.io.InputStream,
- but rather is only required to implement the method
+The
+\family typewriter
+StreamingResponse
+\family default
+ class is similar to the
+\family typewriter
+InMemoryResponse
+\family default
+, except that instead of reading from a buffer, it reads from an input object.
+ The input object is not required to be a subclass of
+\family typewriter
+java.io.InputStream
+\family default
+, but rather is only required to implement the method
\begin_inset Quotes eld
\end_inset
@@ -1459,23 +1477,22 @@ target "http://scala.sygneca.com/patterns/duck-typing-done-right"
function (cleanup, if you will) that is called when the input stream is
exhausted.
- As an example, let's refine the chart code from section
-\begin_inset CommandInset ref
-LatexCommand ref
-reference "sec:Custom-dispatch-func"
-
-\end_inset
-
- to use piped streams instead of sucking the whole chart into memory.
+ As an example, let's look at how we could stream a file from our WAR back
+ to the client.
Listing
\begin_inset CommandInset ref
LatexCommand ref
-reference "lst:refined-Charting-method"
+reference "lst:streaming-download"
\end_inset
- shows how we can use PipedInputStream and PipedOutputStream from java.io
- to send the data back to the user.
+ shows how we can retrieve the input stream from our classloader and then
+ send it directly to the user.
+ Note that you
+\emph on
+must
+\emph default
+ know the size of the file you're streaming before sending it.
\end_layout
\begin_layout Standard
@@ -1489,10 +1506,10 @@ status open
\begin_inset Caption
\begin_layout Plain Layout
-Streaming Charting method
+Streaming download method
\begin_inset CommandInset label
LatexCommand label
-name "lst:refined-Charting-method"
+name "lst:streaming-download"
\end_inset
@@ -1506,73 +1523,63 @@ name "lst:refined-Charting-method"
\begin_layout Plain Layout
-def chart (endDate : String) : Box[LiftResponse] = {
+def sendFile () : Box[LiftResponse] = {
\end_layout
\begin_layout Plain Layout
- // Query, set up chart, etc...
+ // Locate the file and process it
\end_layout
\begin_layout Plain Layout
- val buffered = balanceChart.createBufferedImage(width,height)
+ LiftRules.getResource("/some-file.txt").map { url =>
\end_layout
\begin_layout Plain Layout
- val inPipe = new java.io.PipedInputStream()
+ val input = url.openStream()
\end_layout
\begin_layout Plain Layout
- val outPipe = new java.io.PipedOutputStream(inPipe)
+ val filesize = ...
+ // must compute or predetermine this.
\end_layout
\begin_layout Plain Layout
- val writer = new Thread {
+ StreamingResponse(inPipe,
\end_layout
\begin_layout Plain Layout
- def run () = { ChartUtilities.writeBufferedImageAsPNG(outPipe, buffered)
- }
+ () => { input.close },
\end_layout
\begin_layout Plain Layout
- }.start
+ filesize,
\end_layout
\begin_layout Plain Layout
- Full(StreamingResponse(inPipe,
+ (Content-Type -> "text/plain") :: Nil,
\end_layout
\begin_layout Plain Layout
- () => { inPipe.close; outPipe.close },
+ Nil,
\end_layout
\begin_layout Plain Layout
- -1, // We don't know the size ahead of time
+ 200)
\end_layout
\begin_layout Plain Layout
- (Content-Type -> image/png) :: Nil,
-\end_layout
-
-\begin_layout Plain Layout
-
- Nil,
-\end_layout
-
-\begin_layout Plain Layout
-
- 200))
+ }
\end_layout
\begin_layout Plain Layout
@@ -1586,10 +1593,7 @@ def chart (endDate : String) : Box[LiftResponse] = {
\end_layout
\begin_layout Standard
-Notice that we run the image encoding in a separate thread; if we didn't
- do this then we would block our response thread because the pipe buffer
- would fill while writing the image data out.
- Also note that we use the cleanup function to close the pipes once we're
+Note that we use the cleanup function to close the input stream once we're
done so that we make sure to release resources.
\end_layout

0 comments on commit 41fcc7c

Please sign in to comment.