分类: Java
2009-06-05 12:34:38
下面我们来看一下上传的数据流的结构,首先要在BROWSER端给出一个请求,我们的请求如下(文件名为test1.jsp): <%@ page contentType="text/html; charset=GBK" %> 显示如下: 说明一: 说明二: 请选择上载文件一: 请选择上载文件二: 说明三: 在上载请求页中混杂了表单的三个输入框,及两个上载文件,当然输入框可以更多、更杂,可以有选择框、单选及多选按钮,待上传的文件也可以有三个、四个或所需要的更多。 action="test2.jsp"表示表单将提交到"test2.jsp",另外注意表单属性中必须要有这句:enctype="MULTIPART/FORM-DATA",enctype指定 Form 输入资料的编码方式,“method”属性必须为“post”,这样表单才能提交大量数据,也表示本表单的数据传递将用流操作,“method=get” 表示数据将通过地址栏进行传递,虽然方便快捷,但只适合很少的数据量。 响应端“test2.jsp”页面如下: <%@ page contentType="text/html; charset=GBK" %> <% upBean.doUpload(request); out.println("上载已完成,请查看输出文件"); %> test2.jsp收到请求后,调用一个java bean执行doUpload(request)操作,本操作将完成流(unicode格式)的接收并不做任何处理地将流顺序写入一个文本文件里,读写操作中用了一个缓冲区byte[] readByte,用了一个ServletInputStream 的一个方法readLine(byte[] b, int off,int len)方法读取流,请大家注意,ServletInputStream 流的read Line方法是一次读入指定大小的行,java bean (UpBean.java)代码如下: [code]package com.upload; import java.io.*; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.ServletInputStream; public class UpBean { public void doUpload(HttpServletRequest req) throws ServletException, IOExcept ion{ //首先定义一个文本文件 File file = new File("out.txt"); //readCount 记录从输入流中实际读取的字符数 int readCount; //输入流缓冲区 byte[] readByte = new byte[1024]; //初始化输入流 ServletInputStream servletInputStream = req.getInputStream(); //初始化一个输出流(到文件) FileOutputStream fileOutputStream = new FileOutputStream(file); //循环从读取输入流中读取字节 readCount = servletInputStream.readLine(readByte, 0,readByte.length); while(readCount != -1){ fileOutputStream.write(readByte,0,readCount); readCount = servletInputStream.readLine(readByte, 0, 1024); } //关闭文件流 fileOutputStream.flush(); } }[/code] 为了便于我们阅读流,上载的两个文件为两个 one.txt: one one one one one one two.txt two two two two two two 都准备好以后,我们就可以运行了,运行时请注意,文本部分及文件部分最好不要出现汉字,或其他双字符集字符,尽量采用英文,因为接收是采用的 Unicode字符集,我们未对输入做任何处理。我们在三个输入框输入的字符为,说明一:explain1;说明二:explain2;说明三:explain3,out.txt接收到如下字符: -----------------------------7d2623a3e0286 Content-Disposition: form-data; name="explain1" explain1 -----------------------------7d2623a3e0286 Content-Disposition: form-data; name="explain2" explain2 -----------------------------7d2623a3e0286 Content-Disposition: form-data; name="file1"; filename="C:\test\one.txt" Content-Type: text/plain one one one one one one -----------------------------7d2623a3e0286 Content-Disposition: form-data; name="file2"; filename="C:\test\two.txt" Content-Type: text/plain two two two two two two -----------------------------7d2623a3e0286 Content-Disposition: form-data; name="explain3" explain3 -----------------------------7d2623a3e0286-- 可以很明显的看到,out.txt被“-----------------------------7d2623a3e0286”分成了五节,即表单的每个输入部分都对应一节,结尾部分是“-----------------------------7d2623a3e0286--”,刚好比开始的一段字符在最后多出两个“-”, 每节的第一行是输入内容的说明“Content-Disposition: form-data”,“name="explain1"”表示上载请求项的name,文本输入部分仅这两个说明,如果输入的是文件还用两项说明:“filename="C:\test\one.txt"”,表示输入源,基于ms-windows的ie上载带有完整的路径,netscape及其他浏览器可能只有一个文件名;还有一项是关于输入格式的“Content- Type:text/plain”;表示输入格式是文本类型,如果我们上载的是bmp文件则为“Content-Type: image/bmp”,word文件为“application/msword”...,说明的下面紧接着是一个空行,然后下面才是我们所需的内容。 仔细分析未加修改的输入流格式,有助于我们实现文件与输入文本的准确分离。 通过以上的分析可以看出,准确分离上载的文件及文本信息需要以下要素:1、数据段分割符、结束符(比分割符多出两个“-”);2、输入文本及上载的文件区分标志(文本为“name=”,文件为“filename=”);3、编码格式,可以通过HttpServletRequest 类getCharacterEncoding() 方法取得。4、表单文本部分名称及内容,名称为“name=”后面的字符,内容为该段第三行及以后的内容;5、文件名称及内容,名称为 “filename=”后面的字符,内容为该段第三行及以后的内容。 下面我们将讨论输入流的分离。 程序实现分析 我们首先画出程序实现的主体结构图,请注意判断文件标志(indexOf("filename=")>0),与判断文本标志(indexOf("name=")>0)的顺序,当(indexOf("filename=")>0)成立时,(indexOf("name=")>0)一定也是成立的,所以判断文件要在判断文本前。 分离文件及输入文本,为完整
|