서블릿에서 non-HTML Document Open
자바 서블릿은 HTML 페이지를 웹브라우저에 제공하기 위한 쉬운 방법을 제공 하지만 대부분의 웹사이트는 HTML이 아닌 Document(PDF, Word, Excel)를 가지고 서비스를 주로 합니다.
아래는 서블릿에서 어떻게 클라이언트의 브라우저에 이러한 HTML이 아닌 문서 즉 PDF 또는 MS Word를 보내는 방법 및 서블릿이 어떻게 방화벽을 경유하여 데이터를 보내는지에 대해서 나와 있으니 참고 하시기 바랍니다.
서블릿을 통해 웹 브라우저에 파일을 Open하기 위해서는 간단히 서블릿의 output stream을 이용하면 됩니다.
ServletOutputStream out = res.getOutputStream();
그러나 binary data, multimedia데이터와 같은 non-HTML문서를 오픈하기 위해서는 어떻게 할까요? 아래에서 하나씩 풀어 보도록 하겠습니다.
인터넷에서 multipart, multimedia, binary data등의 전송을 위해서는 MIME protocol을 이용하는데 서블릿의 response 객체에 오픈을 원하는 data의 MIME Type을 기술해야 합니다.
아래 예제에서는 PDF를 다루어 보도록 하겠습니다.
웹 브라우저는 MIME Type을 이용하여 non-HTML File에 대해 어떻게(어떤 플러그인을 통해) 웹 브라우저에서 뿌리는지를 확인하는데 이 정보를 이용하여 해당 데이터를 처리하기 위한 Plug-in은 해당 파일이 브라우저로 다운로드 될 때 구동되어 이를 처리하게 되는 것입니다. 만약 알지 못하는 MIME Type을 가진 non-HTML인 경우엔 웹 브라우저는 이것을 다운로드 하려고 할 것입니다.
자바 서블릿에서는 PDF 파일인 경우에 아래처럼 MIME Type을 기술 합니다.
// MIME type for pdf doc
res.setContentType( "application/pdf" );
MS Word인 경우엔 아래처럼…
// MIME type for MSWord doc
res.setContentType( "application/msword" );
Excel인 경우에는 "application/vnd.ms-excel" 과 같이 기술 합니다.
-------------------------
Content disposition
-------------------------
HTTP response Header인 “content-disposition”은 파일의 presentation 정보에 대해 서블릿에서 기술 할 수 있도록 하는데 이 헤더를 사용 함으로서 파일의 내용을 자동으로 브라우저에서 오픈할지의 여부를 나타낼 수 있습니다.
res.setHeader("Content-disposition","attachment; filename=" +"Example.pdf" );
// attachment - since we don't want to open
// it in the browser, but
// with Adobe Acrobat, and set the
// default file name to use.
Microsoft Word file인 경우에는 다음처럼 기술 합니다.
res.setHeader("Content-disposition","attachment; filename" +"Example.doc" );
-----------------------------
Firewalls
-----------------------------
브라우저가 firewall을 통과해야 한다면 URL Connection을 만들 때 proxy server와 관련된 hostname, port등의 정보 등을 기술하면 되는데 아래의 예를 참고 하세요…
URLConnection conn = url.openConnection();
// Use the username and password you use to
// connect to the outside world
// if your proxy server requires authentication.
String authentication = "Basic " + new sun.misc.BASE64Encoder().encode("username:password".getBytes());
System.getProperties().put("proxySet", "true");
System.getProperties().put("proxyHost", PROXY_HOST); // your proxy host
System.getProperties().put("proxyPort", PROXY_PORT); // your proxy port
conn.setRequestProperty("Proxy-Authorization", authentication);
파일을 읽기 위해서는 URLConnection or URL의 InputStream을 통해 읽으면 되구요…
If you are using the URLConnection, follow this code:
BufferedInputStream bis = new
BufferedInputStream(conn.getInputStream());
If you are using the URL, follow this code:
BufferedInputStream bis = new
BufferedInputStream(url.openStream());
그리고 다음과 같이 InputStream으로부터 서블릿의 OutputStream을 통해 브라우저에 write하면 됩니다.
BufferedOutputStream bos = new
BufferedOutputStream(out);
byte[] buff = new byte[2048];
int bytesRead;
// Simple read/write loop.
while(-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
아래의 전체 예제를 참고 하세요…
---------------------------------------------------------
public void doPost(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException
{
ServletOutputStream out =
res.getOutputStream ();
//---------------------------------------------------------------
// Set the output data's mime type
//---------------------------------------------------------------
res.setContentType( "application/pdf" ); // MIME type for pdf doc
//---------------------------------------------------------------
// create an input stream from fileURL
//---------------------------------------------------------------
String fileURL =
"http://www.adobe.com/aboutadobe/careeropp/pdfs/adobeapp.pdf";
//------------------------------------------------------------
// Content-disposition header - don't open in browser and
// set the "Save As..." filename.
// *There is reportedly a bug in IE4.0 which ignores this...
//------------------------------------------------------------
res.setHeader("Content-disposition",
"attachment; filename=" +=
"Example.pdf" );
//-----------------------------------------------------------------
// PROXY_HOST and PROXY_PORT should be your proxy host and port
// that will let you go through the firewall without authentication.
// Otherwise set the system properties and use URLConnection.getInputStream().
//-----------------------------------------------------------------
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
URL url = new URL( "http", PROXY_HOST,
Integer.parseInt(PROXY_PORT), fileURL );
// Use Buffered Stream for reading/writing.
bis = new BufferedInputStream(url.openStream());
bos = new BufferedOutputStream(out);
byte[] buff = new byte[2048];
int bytesRead;
// Simple read/write loop.
while(-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
} catch(final MalformedURLException e) {
System.out.println ( "MalformedURLException." );
throw e;
} catch(final IOException e) {
System.out.println ( "IOException." );
throw e;
} finally {
if (bis != null)
bis.close();
if (bos != null)
bos.close();
}
}