[Lift] Re: Direct access to response.outputStream?
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?
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?
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?
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?
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.