1

In short I have a Servlet, which retrieves pictures/videos e t.c. from underlying data store.

In order to archive this I need to copy files InputStream to ServletResponce *OutputStream*

From my point of view this is not effective, since I'll need to copy the file in memory before sending it, it would be more convinient to specify InputStream, from which OutputStream would read data and send it straight away, after reading some data in the buffer.

I looked at ServletResponce documentation and it have some buffer for the message data, so I have a few questions regarding it.

Is this the right mechanism? What If I decide not to send the file at the end of Servlet processing? For example: If I have copied InputStream in OutputStream, and then find out that this is not authorized request, and user have no right to see this Object (Mistake in design maybe) I would still send some data to the client, although this is not what I intended, or not.

2 Answers 2

2

To address your first concern, you can easily copy InputStream to OutputStream using IOUtils from Apache Commons Lang:

IOUtils.copy(fileInputStream, servletOutputStream);

It uses 4K buffer, so memory consumption should not be a concern. In fact you cannot just send straight away data from InputStream. At the lowest level the operating system still has to read file contents to some memory location and in order to send it to socket, you need to provide a memory location where the data to be sent resides. Streams are just a useful abstraction.

About your second question: this is how HTTP works: if you start streaming data to the client, servlet container sends all response headers first. If you abort in the middle, from the client perspective it looks like interrupted download.

Sign up to request clarification or add additional context in comments.

1 Comment

I am exactly using IOUtils.copy for my processing already:) The biggest concern is the second question - this is a flow from my perspective, since I would not like to send anything until Servlet processing is over, this could be error prone. 4K buffer is default size of IOUtils buffer, so using another buffer for Servlet processing would not be as effective. What if I would like to send 8K datagrams, I would either need to read twice using IOUtils, or add configurable copy implementation.
0

Is this the right mechanism?

Basically, it is the only mechanism provided by the Servlet APIs. You need to design your servlet with this in mind.

(It is hard to see how it could be done any other way. A read syscall reads data into memory from a device (the disk). A write syscall writes data from memory to a device (the network interface). There is no syscall to transfer data directly from one device to another. The best you can do is to reduce the amount of copying of data within the application. If you use something like IOUtils.copy, it should minimize that as far as possible. The only way you could avoid going through application memort would be to use some special purpose hardware / operating system combination optimized for content delivery.)

However, this is probably moot anyway. In most cases, the performance bottleneck is likely to be movement of data over the network. Data can probably be read from disk to memory, copied, and written to the network interface orders of magnitude faster than it can move through the network to the user's web browser (or whatever).

If it is NOT moot, then a practical way to do content delivery would be to use a separate web server implemented in native code that us optimized for delivering static content; e.g. something like nginx.)

What If I decide not to send the file at the end of Servlet processing? For example: If I have copied InputStream in OutputStream, and then find out that this is not authorized request, and user have no right to see this Object (Mistake in design maybe) I would still send some data to the client, although this is not what I intended, or not.

You should write your servlet to do the access checks BEFORE reading the content into memory. And ideally, before you "commit" the response by sending the response header.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.