实例:JSP文件上传下载管理

  在这个程序中,将利用流上传文件,利用基于对象流的文件操作保存文件列表,并将文件定向到客户端完成下载。

  表单页面提交上传文件。文件以流的格式传输到服务器上,并被保存为一个临时文件。这个临时文件不仅包含上传文件的内容,还包含了文件信息相关的报头。文件上传程序需要分析报头,从中提出有用的文件信息。将文件信息保存在一个支持序列化借口的Java类中,并以对象流的方式写入文件。上传的文件内容也从临时文件中提出,保存在文件系统中。页面同时也以对象流的方式读取保存了上传列表的内容,将文件相关信息回复到Java类中,然后显示在界面上。

  为了完成下载过程,程序以流的方式读取文件内容,并将其重定向到response对象的输出流上。同时文件相关信息也以HTTP报头的形式发送给客户端。客户端能根据HTTP报头得到文件相关信息,弹出下载对话框。

 

1.序列化Java类FileItem

  首先是设计一个序列化的Java类存储必要的文件信息,例如文件名,文件路径,上传时间,文件大小,文件类型等。

 1 package samples.javabean;
 2 
 3 import java.io.Serializable;
 4 import java.sql.Timestamp;
 5 
 6 public class FileItem implements Serializable {
 7     String name;
 8     Integer length;
 9     String path;
10     String contentType;
11     Timestamp createAt;
12     public FileItem(){
13         this.name="default user";
14         this.length=new Integer(0);
15         this.path="--";
16         this.createAt=new Timestamp(System.currentTimeMillis());
17     }
18     public String getName() {
19         return name;
20     }
21     public void setName(String name) {
22         this.name = name;
23     }
24     public Integer getLength() {
25         return length;
26     }
27     public void setLength(Integer length) {
28         this.length = length;
29     }
30     public String getPath() {
31         return path;
32     }
33     public void setPath(String path) {
34         this.path = path;
35     }
36     public String getContentType() {
37         return contentType;
38     }
39     public void setContentType(String contentType) {
40         this.contentType = contentType;
41     }
42     public Timestamp getCreateAt() {
43         return createAt;
44     }
45     public void setCreateAt(Timestamp createAt) {
46         this.createAt = createAt;
47     }
48     
49 
50 }

 

2.上传处理程序

  上面的FIleItem类支持了序列化的接口,可以通过对象流进行读写。

  本例子中将FileItem类存入到一个ArrayList类对象,并存储在文件中filelist.log.

  下面的代码是页面部分。提供了一个文件上传表单。表单的input控件为file类型。表单的action指向了处理上传文件的Ex6_11_1.jsp。同时页面读取filelist.log文件,以基于对象流的方式读取保存文件列表的ArrayList,并将其存储的每个FileItem对象的信息现实在页面上。

 

 1 <%@page import="com.sun.org.apache.bcel.internal.generic.NEWARRAY"%>
 2 <%@ page language="java" contentType="text/html; charset=GB18030"
 3     pageEncoding="GB18030"%>
 4 <%@ page import="java.io.*" %>
 5 <%@ page import="java.util.*" %>
 6 <%@ page import="samples.javabean.*" %>
 7 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 8 <html>
 9 <head>
10 <meta http-equiv="Content-Type" content="text/html; charset=GB18030">
11 <title>文件上传下载管理</title>
12 <%
13     File file=new File("/home/jim/Development/apache-tomcat-7.0.30/webapps/ROOT/filelist.log");
14     if(!file.exists()){
15         file.createNewFile();
16         ObjectOutputStream newfile=new ObjectOutputStream(
17                 new FileOutputStream(file));
18         ArrayList list=new ArrayList();
19         newfile.writeObject(list);
20         newfile.flush();
21         newfile.close();
22     }
23 %>
24 </head>
25 <body>
26 <font size="2">
27 <form name="upload" method="post" action="Ex6_11_1.jsp"
28     enctype="multipart/form-data">
29     上传文件<input type="file" name="file">
30     <input type="submit" name="提交" value="Submit">
31 </form>
32 <%
33     ObjectInputStream o=new ObjectInputStream(
34             new FileInputStream(file));
35     ArrayList list=(ArrayList)o.readObject();
36     o.close();
37     if(list==null) list=new ArrayList();
38     for(Iterator it=list.iterator();it.hasNext();){
39         FileItem item=(FileItem)it.next();
40         out.print(item.getName()+":");
41         out.print("&nbsp;&nbsp;&nbsp;&nbsp;"+item.getLength()+"字节");
42         out.print("&nbsp;&nbsp;&nbsp;&nbsp;上传时间("+item.getCreateAt()+
43         ")");
44         out.print("<a href=\"Ex6_11_2.jsp?filename="+item.getName()
45                 +"&Type="+item.getContentType()+"\">下载</a><br>");
46     }
47 %>
48 </font>
49 
50 </body>
51 </html>

  单击确定按钮,表单将内容传送到action指向的程序。文件内容也包含在其中。可以使用request.getInputStream()方法获取输入流。然后将流的内容保存到一个文件中。但是这样的文件的内容并不完全是客户端选择的文件的内容.而是如图所示:

许多额外内容被保存到文件中,例如Content-Disposition域和Content-Type域。这些额外的信息可以称为报头。是HTTP协议通信时附加的。报头包含了一些有用的文件信息。因此,为了完成文件上传功能,必须分析这个包含报头的文件,取出里面的与文件相关的信息和文件内容。

  文件的第二行的最后一部分包含了文件名。第三行包含了文件类型,第四行到倒数第六行是文件的内容。

下面的代码显示了如何具体街区报头中的信息:

  1 <%@ page language="java" contentType="text/html; charset=GB18030"
  2     pageEncoding="GB18030"%>
  3 <%@ page import="java.io.*" %>
  4 <%@ page import="java.util.*" %>
  5 <%@ page import="samples.javabean.*" %>
  6 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  7 <html>
  8 <head>
  9 <meta http-equiv="Content-Type" content="text/html; charset=GB18030">
 10 <title>Insert title here</title>
 11 </head>
 12 <body>
 13 <%
 14     try{
 15         File filelist=new File("/home/jim/Development/apache-tomcat-7.0.30/webapps/ROOT/filelist.log");
 16         File tempfile=new File("/home/jim/Development/apache-tomcat-7.0.30/webapps/ROOT/"+session.getId());
 17         //将表单所有内容存入临时文件
 18         int buffersize=4096;
 19         byte buffer[]=new byte[buffersize];
 20         FileOutputStream o =new FileOutputStream(tempfile);
 21         request.setCharacterEncoding("GB18030");
 22         InputStream in=request.getInputStream();
 23         int count;
 24         while((count=in.read(buffer))!=-1){
 25             o.write(buffer, 0, count);
 26         }
 27         o.close();
 28         in.close();
 29         //从包含表单数据的临时文件中提取文件信息
 30         RandomAccessFile random=new RandomAccessFile(tempfile,"r");
 31         //第2行是Content-Disposition,其中最后一项是文件名
 32         int linenum=1;
 33         String fileheader=null;
 34         while(linenum<=2){
 35             fileheader=random.readLine();
 36             linenum++;
 37         }
 38         int pos=fileheader.lastIndexOf('=');
 39         String filename=fileheader.substring(pos+2, fileheader.length()-1);
 40         //第三行是文件类型
 41         String contenttype=random.readLine();
 42         pos=contenttype.lastIndexOf(':');
 43         contenttype=contenttype.substring(pos+1);
 44         //第四行至倒数第六行是文件实际内容
 45         //先找出第四行的文件指针位置
 46         linenum=1;
 47         random.seek(0);
 48         int newline;
 49         long offset_start=0,offset_end=0;
 50         while((newline=random.readByte())!=-1&&linenum<=4){
 51             if(newline=='\n'){
 52                 offset_start=random.getFilePointer();
 53                 linenum++;
 54             }
 55         }
 56         //找出倒数第六行文件指针位置
 57         File uploaddir=new File("/home/jim/Development/apache-tomcat-7.0.30/webapps/ROOT/upload");
 58         if(!uploaddir.exists()) uploaddir.mkdir();
 59         File newfile=new File(uploaddir,filename);
 60         RandomAccessFile random2=new RandomAccessFile(newfile,"rw");
 61         random.seek(random.length());
 62         offset_end=random.getFilePointer();
 63         long fp=offset_end;
 64         linenum=1;
 65         while(fp>=0&&linenum<=6){
 66             fp--;
 67             random.seek(fp);
 68             newline=random.readByte();
 69             if(newline=='\n'){
 70                 offset_end=random.getFilePointer()-1;
 71                 linenum++;
 72             }
 73         }
 74         random.seek(offset_start);
 75         //将临时文件中文件实际内容存储到新的文件
 76         long start=random.getFilePointer();
 77         while(start<offset_end-1){
 78             byte b=random.readByte();
 79             random2.write(b);
 80             start=random.getFilePointer();
 81         }
 82         //记录存储的文件,以对象的方式保存到文件中
 83         FileItem item=new FileItem();
 84         item.setName(filename);
 85         item.setLength(new Integer((int)random.length()));
 86         item.setPath(newfile.getPath());
 87         item.setContentType(contenttype);
 88         ObjectInputStream o1=new ObjectInputStream(new FileInputStream(filelist));
 89         ArrayList list=(ArrayList)o1.readObject();
 90         o1.close();
 91         if(list==null) list=new ArrayList();
 92         list.add(item);
 93         ObjectOutputStream output=new ObjectOutputStream(new FileOutputStream(filelist));
 94         output.writeObject(list);
 95         output.flush();
 96         output.close();
 97         random2.close();
 98         random.close();
 99         response.sendRedirect("Ex6_11.jsp");
100     }catch(IOException e){}
101 %>
102 </body>
103 </html>

程序运行结果为:

 

3.文件下载程序

  接下来是实现文件下载功能。最简单的方法是直接给出文件的URL。但这样需要把文件暴露在WEb服务器的路径下。而且会暴露文件的实际路径信息。更好的方法是采用流读取文件,重定向到response对象的输出流。下面是具体的代码:

 1 <%@ page language="java" contentType="text/html; charset=GB18030"
 2     pageEncoding="GB18030"%>
 3 <%@ page import="java.io.*" %>
 4 <%@ page import="java.util.*" %>
 5 <%@ page import="samples.javabean.*" %>
 6 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 7 <html>
 8 <head>
 9 <meta http-equiv="Content-Type" content="text/html; charset=GB18030">
10 <title>Insert title here</title>
11 </head>
12 <body>
13 <font size="2">
14 <%
15     request.setCharacterEncoding("GB18030");
16     String filename=request.getParameter("filename");
17     String contenttype=request.getParameter("Type");
18     OutputStream o=response.getOutputStream();
19     int buffersize=4096;
20     byte[] buffer=new byte[buffersize];
21     File uploaddir=new File("/home/jim/Development/apache-tomcat-7.0.30/webapps/ROOT/upload/");
22     File download=new File(uploaddir,filename);
23     //设置Content-Disposition
24     response.setHeader("Content-Disposition", "attachment;filename="+filename);
25     //设置文件类型
26     response.setContentType(contenttype);
27     //设置文件大小
28     response.setHeader("Content_Length", download.length()+"");
29     //读取文件流写入输出
30     FileInputStream in =new FileInputStream(download);
31     int count;
32     while((count=in.read(buffer))!=-1){
33         o.write(buffer,0,count);
34     }
35     in.close();
36     o.close();
37 %>
38 </font>
39 </body>
40 </html>

单击下载,显示如下结果:

 

 

 

posted @ 2012-10-29 16:55  Jim-Huang  阅读(544)  评论(0编辑  收藏  举报