0

I have storaged in file in my database (format byte[]) and the name and format of the file.

Now i convert my bytearray into an InputStream. How can i recreated the specific file with this InputStream, which was saved in the database before? For example, a PDF document must be a PDF document and a txt file muste be a txt file.

I work with jsf and this is my current code:

Dto currentDto = //code to get the file from the database

final FacesContext facesContext = FacesContext.getCurrentInstance();
final ExternalContext externalContext = facesContext.getExternalContext();
final HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

InputStream inputStream = new ByteArrayInputStream(currentDto.getFileBytes());
OutputStream outputStream = response.getOutputStream();
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555

1 Answers1

1

Set the Content-Type header in the response. During saving the file in the DB, you should have determined the file's content type or at least the original file extension.

Imagine that you have obtained the file name of the uploaded file as follows, using Apache Commons IO:

String filename = FilenameUtils.getName(uploadedFile.getName());

Then you could determine the content type as follows:

ServletContext servletContext = (ServletContext) externalContext.getContext();
String contentType = servletContext.getMimeType(filename);

Save it along the file content in the DB so that you can upon retrieval do:

byte[] content = currentDto.getFileBytes(); // Terrible classname, by the way.
String contentType = currentDto.getFileContentType();

Finally send it to the HTTP response as follows (no need for massaging it into InputStream):

response.setContentType(contentType);
response.setContentLength(content.length);
response.setHeader("Content-Disposition", "attachment");
response.getOutputStream().write(content);

Alternatively, save the filename instead of the content type in the DB and do the ServletContext#getMimeType() during streaming the file download only:

response.setContentType(servletContext.getMimeType(filename));

The filename is namely also useful for Content-Disposition header, the sane webbrowser (read: everything but MSIE, it uses the last path in request URL instead) will use it as Save As filename.

response.setHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I use JSF 1.2 and the method "externalContext.getMimeType" doesn´t exists. Soprry i forgot it to say it. –  Oct 31 '13 at 10:24
  • Then use the low-level `ServletContext` and `HttpServletResponse` APIs directly. I updated the answer. – BalusC Oct 31 '13 at 10:26
  • Many thanks for for posting! Is it possible to popup an operation system´s dialog to save this file on my harddisk? Now i can see the file content in my browser window. –  Oct 31 '13 at 10:39
  • Set `Content-Disposition` header to `attachment`. I updated the answer. – BalusC Oct 31 '13 at 10:43
  • sorry i set this already but the browser window shows me the file content again –  Oct 31 '13 at 11:02
  • Apparently you've configured the browser to always show the specified content type inline. Reconfigure your browser or try a different browser/machine. See also e.g. http://stackoverflow.com/questions/13231597/how-to-show-file-save-file-dialog-box-while-click-download-button/13231817#13231817 – BalusC Oct 31 '13 at 11:08
  • sorry but that doesn´t cause the problem. Problem must be initialze by another fact. I work with this code in a jsf actionListener method, cause this the problem? –  Oct 31 '13 at 11:16
  • No, the problem is in the client side. E.g. bad configuration or overzealous cache. – BalusC Oct 31 '13 at 11:23
  • sorry, i have test it in differnt browsers on different clients, the result is always the same. Must be specific Request header set, if i want to download a file? –  Oct 31 '13 at 11:40
  • Then you're not running the code provided in the answer. Perhaps you've set the header *after* writing the file content? Checking HTTP/Network traffic monitor in webbrowser (press F12) should give clues. – BalusC Oct 31 '13 at 11:43
  • I set the methods outputStream.flush();, outputStream.close(); and facesContext.responseComplete(); at the end of the code. Is that right? –  Oct 31 '13 at 11:47
  • Ok the problem was that i used an ajax commandlink and not a jsf commandlink in my jsf page. Terrible mistake ! –  Nov 01 '13 at 12:02
  • You indeed can't download files with ajax. – BalusC Nov 01 '13 at 12:12