A Funny Java Flavoured Look at the World

Tuesday, March 27, 2007

taking a url and passing it back an outputstream in a jsp

Today someone wanted to pass in the name of a file located somewhere inside a web application and then stream that file back to them. In this example they wanted to open a pdf file. We only wanted a quick dirty piece of code put in a jsp, which was okay with me being the cowboy coder I am.

The first tricky point was they were giving me a URL and wanted back a file. I have tangled with this problem before of translating a url to get to a file but of course I couldn't remember how I did it.

After searching on the internet for a bit I found this piece of code

http://www.exampledepot.com/egs/java.net/Post.html

I did have an example first of getting a file and then sending that back through the outputstream of the jsp (which is really a servlet as we all know). It was interesting that I got this task because I had been reading about this in my SCWCD book whilst studying (very slowly) for the exam.

this is what what the code was for the reading a file

//resources//docs//CodeConventions.pdf

response.addHeader("content-disposition","attachment; filename=" + fileName);

fileName = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/resources/docs/CodeConventions.pdf";

URL url = new URL(fileName);
URLConnection conn = url.openConnection();
conn.setDoOutput(true);

File f = new File(fileName);
byte[] bytearray = new byte[(int) f.length()];
FileInputStream is = new FileInputStream(f);
response.setIntHeader("content-length", (int) f.length());
is.read(bytearray);
OutputStream os = response.getOutputStream();
os.write(bytearray);
os.flush();


The deal was that I was going to be passed in the relative url, so the person would pass in the url to the file relative from the root of the web app. This allow me to use the servlets request.getContext and getServer() to generate the first part of the url

here is the final code, it differs because it gets a url and then gets a connection to that url and reads off the data before passing that into the output stream of the servlet/jsp. Its pretty messy but it works.

<%@ page import="java.lang.Integer" %>
<%@ page import="java.io.BufferedInputStream" %>
<%@ page import="java.io.ByteArrayOutputStream" %>
<%@ page import="java.io.FileInputStream" %>
<%@ page import="java.io.FileReader" %>
<%@ page import="java.io.File" %>
<%@ page import="java.io.FileInputStream" %>
<%@ page import="java.io.FileReader" %>
<%@ page import="java.io.OutputStream" %>
<%@ page import="java.io.OutputStream" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.net.URL" %>
<%@ page import="java.net.URLConnection" %>
<%


response.setContentType("application/pdf");
String fileName = "not set";
if (request.getParameterValues("docname")[0] != null){
fileName = (String) request.getParameterValues("docname")[0];
}


response.addHeader("content-disposition","attachment; filename=" + fileName);

response.setContentType("application/pdf");
fileName = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + fileName;
URL url = new URL(fileName);
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
BufferedInputStream buf=new BufferedInputStream(conn.getInputStream());//for better performance
OutputStream os = response.getOutputStream();

byte[] buffer=new byte[1024];//byte buffer
int bytesRead=0;
while (true){
bytesRead=buf.read(buffer,0,1024);
// bytesRead returns the actual number of bytes read from
// the stream. returns -1 when end of stream is detected
if (bytesRead == -1) break;
os.write(buffer,0,bytesRead);
}

if(buf!=null) {
buf.close();
}
if(os!=null) {
os.close();
}


os.flush();
%>