[Lift] Re: Direct access to response.outputStream?

2010-02-26 Thread Marius


On Feb 26, 11:50 am, Jeppe Nejsum Madsen je...@ingolfs.dk wrote:
 Hi,

 I need to create a response that downloads a file. The file is
 generated by a 3rd party api that takes an output stream as the target
 for the file. As the file can be rather large, I would like to stream
 this file directly to the client.

 I've looked at StreamingResponse, but this seem to require something
 akin to an input stream.

 As there a way to generate a response with direct access to the output stream?


No. IMO this would bring serious problems related with committed
response if people will start writing directly into servlet's
response output stream. But you should be able to bridge the
outputstream needed by that library and the inputstream from the
StreamingResponse ( which takes a structural type not really an
InputStream) through mechanisms similar with Pipes. You could also
build your own OutputStream that also has def read(buf: Array[Byte]):
Int. Thus your library will write stuff in your OutputStream, you
would then buffer the data and wait for that data to be drained by the
servlet's input stream. A simple producer/consumer approach.


 /Jeppe

-- 
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.



Re: [Lift] Re: Direct access to response.outputStream?

2010-02-26 Thread Jeppe Nejsum Madsen
Marius marius.dan...@gmail.com writes:

 On Feb 26, 11:50 am, Jeppe Nejsum Madsen je...@ingolfs.dk wrote:
 Hi,

 I need to create a response that downloads a file. The file is
 generated by a 3rd party api that takes an output stream as the target
 for the file. As the file can be rather large, I would like to stream
 this file directly to the client.

 I've looked at StreamingResponse, but this seem to require something
 akin to an input stream.

 As there a way to generate a response with direct access to the output 
 stream?


 No. IMO this would bring serious problems related with committed
 response if people will start writing directly into servlet's
 response output stream.

Normally, yes. But I think there are special cases that may warrant this
and I tend to think this is one of them :-)

 But you should be able to bridge the outputstream needed by that
 library and the inputstream from the StreamingResponse ( which takes
 a structural type not really an InputStream) through mechanisms
 similar with Pipes. 

But unless I create a new thread, I'll still end up with the entire file
in memory. Ie the call to the library's write method must return before
the streaming response can be created and thus the file contents must
be stored somewhere.

 You could also build your own OutputStream that also has def read(buf:
 Array[Byte]): Int. Thus your library will write stuff in your
 OutputStream, you would then buffer the data and wait for that data to
 be drained by the servlet's input stream. A simple producer/consumer
 approach.

If I create a new thread I could probably use PipedOutputStream which
does this already. But still the file contents will be copied twice: 1)
From pipe output to pipe input, 2) from pipe input to response output

So the thread creation/scheduling and the two times file copying could be
avoided by writing directly to the output stream. But I agree this would
have to be special cased somehow. It's not an urgent issue atm, but I'll
try to see if some clean solution can be implemented.

/Jeppe

-- 
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.



Re: [Lift] Re: Direct access to response.outputStream?

2010-02-26 Thread Jeppe Nejsum Madsen
On Fri, Feb 26, 2010 at 12:06 PM, Jeppe Nejsum Madsen je...@ingolfs.dk wrote:

 So the thread creation/scheduling and the two times file copying could be
 avoided by writing directly to the output stream. But I agree this would
 have to be special cased somehow. It's not an urgent issue atm, but I'll
 try to see if some clean solution can be implemented.

An idea just struck :-) Could this be handled in much the same way as
a redirect? Something like

S.sendFile(application/pdf, myfilename.pdf, outputStream =
mylibrary.write(outputStream))

this would throw an exception like ResponseShortcutException, lift
would intercept it, write the appropriate headers and execute the
passed function with the response outputstream as parameter.

This would prohibit accidental output to response.

Thoughts?

/Jeppe

-- 
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.



[Lift] Re: Direct access to response.outputStream?

2010-02-26 Thread Marius


On Feb 26, 1:29 pm, Jeppe Nejsum Madsen je...@ingolfs.dk wrote:
 On Fri, Feb 26, 2010 at 12:06 PM, Jeppe Nejsum Madsen je...@ingolfs.dk 
 wrote:

  So the thread creation/scheduling and the two times file copying could be
  avoided by writing directly to the output stream. But I agree this would
  have to be special cased somehow. It's not an urgent issue atm, but I'll
  try to see if some clean solution can be implemented.

 An idea just struck :-) Could this be handled in much the same way as
 a redirect? Something like

 S.sendFile(application/pdf, myfilename.pdf, outputStream =
 mylibrary.write(outputStream))

 this would throw an exception like ResponseShortcutException, lift
 would intercept it, write the appropriate headers and execute the
 passed function with the response outputstream as parameter.

 This would prohibit accidental output to response.

 Thoughts?

I would prefer something like :

final case class OutputStreamingResponse(data: (OutputStream) = Unit,
size: Long, headers: List[(String, String)], cookies:
List[HTTPCookie], code: Int) extends BasicResponse {
..
}

hence remain consistent with Lift's response paradigm.

We *COULD* provide the OutputStrem from the servlet response but that
would be ok since we are in a LiftResponse and NOT inside the
rendering pipeline.


 /Jeppe

-- 
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.



Re: [Lift] Re: Direct access to response.outputStream?

2010-02-26 Thread Jeppe Nejsum Madsen
On Fri, Feb 26, 2010 at 1:53 PM, Marius marius.dan...@gmail.com wrote:


 On Feb 26, 1:29 pm, Jeppe Nejsum Madsen je...@ingolfs.dk wrote:
 On Fri, Feb 26, 2010 at 12:06 PM, Jeppe Nejsum Madsen je...@ingolfs.dk 
 wrote:

  So the thread creation/scheduling and the two times file copying could be
  avoided by writing directly to the output stream. But I agree this would
  have to be special cased somehow. It's not an urgent issue atm, but I'll
  try to see if some clean solution can be implemented.

 An idea just struck :-) Could this be handled in much the same way as
 a redirect? Something like

 S.sendFile(application/pdf, myfilename.pdf, outputStream =
 mylibrary.write(outputStream))

 this would throw an exception like ResponseShortcutException, lift
 would intercept it, write the appropriate headers and execute the
 passed function with the response outputstream as parameter.

 This would prohibit accidental output to response.

 Thoughts?

 I would prefer something like :

 final case class OutputStreamingResponse(data: (OutputStream) = Unit,
 size: Long, headers: List[(String, String)], cookies:
 List[HTTPCookie], code: Int) extends BasicResponse {
 ..
 }

 hence remain consistent with Lift's response paradigm.

 We *COULD* provide the OutputStrem from the servlet response but that
 would be ok since we are in a LiftResponse and NOT inside the
 rendering pipeline.

Agreed, a cleaner solution. And this could also be used outside of a
stateful response. The size should probably be Box[Long] as it may be
unknown.

Should I create a ticket for this?

/Jeppe

-- 
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.