views:

24

answers:

3

Hi All.

This is the situation:

We have some binary files (PDFs, PPTs, ZIPz, etc.) stored in a server different from where our application is. We need to make them available for the users in our app. But files have extremely sensitive information that can not be read by anyone else but the user that has access to them which means that we need to validate the user that is trying to access the file before s/he can download it.

This is how we solve it:

  1. We get the file from the remote server, store it in a non public location.
  2. We read the file into a byte array, then we delete the file.
  3. We write the file through a JSP using the response's outputStream. (We can not flush it through the servlet because we are using a proprietary MVC that we cannot modify, so all outputs are JSPs, so we get a java.lang.IllegalStateException but it works).

I'm concerned by 3 aspects of this solution; The file size will impact the heap size dramatically, the file size is limited to a max of byte[Integer.MAXSIZE] and finally we get an java.lang.IllegalStateException every time someone downloads a file because we are calling the response.getOutputStream(), so our log is growing a lot.(We can not flush it through the servlet because we are using a proprietary MVC that we cannot modify or extend)

I'm pretty sure there is a more elegant way to do this.

Any ideas?

A: 

Skip step 2 and read the file directly into the response's output stream.
Give each file a UUID for a name, so you do not have clashes with the file names. Have a daemon process go and cleanup any files more than 15 minutes old.

Romain Hippeau
Those are good improvements but the core issues still remain
Chepech
+2  A: 

Indeed just don't store it locally. You're getting it as an InputStream from somewhere else, right? Just write it immediately to the OutputStream of the response. Then there's no need to get hold of it in Java's memory nor local disk file system. This means that you should put the logic for obtaining the file in the JSP file. Bad, bad, but since this is apparently a proprietary framework...

Then the IllegalStateException part, you just need to ensure that there is no whitespace outside the scriptlets, including newlines. It will all implicitly be written through response.getWriter(), but this isn't possible because you already called response.getOutputStream() for the file. Remove everything outside <% %> in the JSP. Glue if necessary multiple scriptlets together. Don't forget to remove the last newline at the bottom of the file.

E.g. not so:

<%@ page import="java.io.*" %>
<% ... %>
<% ... %>
<% ... %>
 

But more so:

<%@ page import="java.io.*" %><%
   ...
   ...
   ... %>

Good luck with this webapp.

BalusC
We just eliminated the IllegalStateException with the tick you shared.So its one less dirty secret we need to hide from the people paying this... =P
Chepech
A: 

Probably the most elegant solution would be to use an existing open source software product. I believe Knowledge Tree would satisfy your requirements.

emory