Java技巧:怎样从servlet打开一个非html文件

类别:Java 点击:0 评论:0 推荐:

1、摘要

Java Servlet 程序提供了一个简单的方式发送HTML文件到客户端浏览器。但是,现在一些站点提供了一些非HTML的存取文件,例如Adobe PDF,Microsoft Word, 和 Microsoft Excel 文件等。这篇文章以使用PDF和WORD为例子讲解怎样从SERVLET发送一个非HTML文件到客户端浏览器。事实上,通过本文,你可以通过MIME类型发送任何的格式的文件。同时,也能了解到通过SERVLET怎样与防火墙进行交互。

      通过一个SERVLET在浏览器中打开一个文件,你只需简单的把这个文件加入到SERVLET的输出流中。尽管这么做看起来很简单,但是当你打开一个非HTML文件时你必须需要一些事情,例如二进制文件和多个文件的问题。

      你可以通过一下方式得到SERVLET输出流:

ServletOutputStream out = res.getOutputStream();

互联网通过MIME(多用途网络邮件扩展)协议发送多部分,多媒体和二进制文件。在SERVLET的RESPONSE对象中,设置你想打开的文件的MIME类型是非常重要的。

2、MIME类型

    客户端浏览器通过MIME类型来识别非HTML文件和决定用什么包容器来呈现这个数据文件。插件能够通过MIME类型来决定用什么方式来打开这些文件,当我们下载这些文件以后,我们通过浏览器就可以浏览这些文件了。

    MIME类型很有用,他们允许浏览器通过内置技术处理不同的文件类型。

    MIME类型对于一个PDF文件是"application/pdf"。当在SERVLET打开一个PDF文件时,你必须在RESPONSE最前面设置"application/pdf":

// MIME type for pdf doc
    res.setContentType( "application/pdf" ); 

打开一个WORD文档,你应该设置成"application/msword":

// MIME type for MSWord doc
    res.setContentType( "application/msword" );

对于EXCEL文档,使用MIME类型是"application/vnd.ms-excel"。如果需要的插件系统没有没有安装,浏览器会出现一个提示框,询问用户是否在当前位置打开还是保存到磁盘上。

3、内容部署

      部署内容的HTTP response 头允许servlet指定文件类型的信息。使用这个头说明,你可以制定特定的方式来打开这个文件(不仅仅在浏览器中),而且它不应该自动的显示。你可以设置要保存的文件名。这个文件应该是对话框中显示的文件名。如果你不想指定文件名,你得到的是你的servlet同名的文件名称。

      在SERVLET中你可以象下面的代码一样来设置头

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.

如果你想打开一个WORD文件,应该如下做:

res.setHeader("Content-disposition",
                  "attachment; filename" +
                  "Example.doc" );

4、封装

       剩下的工作就很简单了。你需要基于你想打开的文件的名字创建一个java.net.URL对象。这个字符串应该完整的指出这个文件的位置。举例说明:

String fileURL =
http://www.adobe.com/aboutadobe/careeropp/pdfs/adobeapp.pdf;

你的url字符串应该象http://www.gr.com/pub/somefile.doc或者

http://www.gr.com/pub/somefile.xls这个样子。

    但是你必须确认你所打开的文件与你MIME类型中指定的文件类型一定要一致。

URL url = new URL ( fileURL );

5、防火墙

    如果你的浏览器需要通过防火墙,最后的一件事情就是你需要担心的就是你的URL连接了。你需要找出一些你的代理服务器的一些信息,例如主机名称和端口号去与防火墙建立连接。如果你使用JAVA 2,你应该创建一个URL连接对象,设置以下的系统属性:

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);

如果你使用JDK 1.1你可以不用建立系统属性。你应该用你的代理服务器信息创建JAVA.NET.URL对象。

url = new URL("http", PROXY_HOST,
                  Integer.parseInt(PROXY_PORT),
                  fileURL );
    // assumes authentication is not required

6、实现

    在开始读取你得文件的时候,你需要从URLConnection (or URL)对象中包含InputStream。   

       在以下的例子中,你用一个BufferedInputStream来限制这个InputStream。

    如果你正在使用这个URLConnection,以下就是这样的代码:

BufferedInputStream  bis = new BufferedInputStream(conn.getInputStream());

如果你正在使用URL,那就象以下的代码:

BufferedInputStream  bis = new BufferedInputStream(url.openStream());

一旦做完以上工作,你只需简单的从输入流写出每一个字节到servlet的输出流中

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);
    }

最后,在最后的模块中关闭这个流。

这个例子通过使用一个servlet的doPost方法来实现这个功能。

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();
    }
}

7、总结

    正如你所看到的,在一个servlet中打开一个非HTML是很简单的,甚至在一个防火墙之外。你可以使用同样的代码打开图像文件或者其他类型的多媒体文件,只要正确设置MIME类型。今天,在互联网上更多的信息都变得有效了,并且其中大量的信息是以非HTML类型存储的。相比之下,开发一个servlet来呈现非HTML文档是一件容易,方便的方式来提供给你的用户更多的信息。

 

本文地址:http://com.8s8s.com/it/it17733.htm