首页 >> 读书频道 >> 电脑 >> 用JavaBean实现文件上载(四)方法
 
· Java程序的反编译问题
· Java应用技巧(一)
· MVC减少编程复杂性
· Struts中使用Val
· Eclipse+JBos
· 关掉那可恶的Dos窗口
· Jakarta Stru
· JavaBean使用技巧
· JSP与Servlets
· JAVA和C++区别
· 应用Java技术实现数据
· Java能够成为完美的技
 
· 红楼梦:120回全本[清
· 素质教育在美国
· 全唐诗卷四十六
· 韩剧《布拉格恋人》剧情介
· 夜航船[作者:明·张岱]
· 局外人[作者:韩·可爱淘
· 现场流行病学
· 源氏物语[日本:紫式部]
· 武林寓言故事
· 2006高考录取规则
· 首批中国世界名牌产品和2
· 济南美食大全
 
· (出租)中动商场部分及写
· (出租)中动动漫基地&#
· 喜剧学院
· 《善德女王》剧情介绍
· 魔女18号 剧情
· 丑女无敌剧情介绍
· 魔女幼熙剧情介绍
· 龙游天下剧情介绍
· 震撼世界的七日剧情介绍
· 静静的白桦林剧情介绍
· 心情日记—老公今天我想对
· 旗舰剧情介绍
欢迎来到月影社区!如果您觉得这里不错,请推荐给您的朋友们。月影社区:http://wf66.com/

用JavaBean实现文件上载(四)方法


查看有无更新版本

关键字:JAVA 2006-8-31

 

前面四个public类型的方法用于返回FileUploadBean对象的私有域,它们是:getFilepath,getFilename,getContentType以及getFieldValue。
public String getFilepath()
返回filepath私有域的值。
public String getFilename()
返回filename私有域的值。
public String getContentType()
返回contentType私有域的值。
public String getFieldValue(String fieldName)
返回HTML表单中指定输入元素的值,元素的名字通过fieldName参数指定。
public void setSavePath(String savePath)
用该方法指定服务器上保存上载文件的目录的名字。
 
public void doUpload(HttpServletRequest request) throws IOException
doUpload是FileUploadBean类中最重要的一个方法。它的任务有二个:第一,它从HTML表单提取出输入域的名字和值并保存到Dictionary对象;第二,doUpload方法提取出上载的文件,把这个文件保存到savePath指定的路径,并分别把文件的名字、路径、内容类型赋给filename、filepath和contentType域。
private void setContentType(String s)
由doUpload方法调用。setContentType方法从原始字节数据提取出上载文件的内容类型。
private void setFilename(String s)
由doUpload方法调用。setFilename方法从原始字节数据提取出文件路径和名字。
doUpload方法的参数是Servlet/JSP容器创建的HttpServletRequest对象。HttpServletRequest对象描述了程序为了提取出HTML表单元素名字-值对以及上载文件必须处理的HTTP请求。doUpload方法首先通过HttpServletRequest对象的getInputStream方法获得ServletInputStream对象。
如前所述,每一个表单元素由分界符和一组回车换行符分隔。因此,我们可以一行一行地读入HttpServletRequest对象的内容。下面这行代码定义了一个名为line的byte数组:
然后,我们用ServletInputStream对象的readLine方法读入HttpServletRequest对象内容的第一行:
int i = in.readLine(line, 0, 128);
第一行应该是分界符,而且如果没有错误的话,它的长度应该大于3。如果它的长度小于3,我们可以认为出现了错误,doUpload方法应该立即返回:
if (i < 3)
return;
分界符和分界符的长度都非常重要,从本文后面你可以看到这一点。分界符由一组回车换行符结束,因此它的实际长度要比readLine方法返回的字节数少2。
int boundaryLength = i - 2;
丢弃byte数组line的最后2个回车换行符即可获得分界符:
String boundary = new String(line, 0, boundaryLength);
接下来,fields域被实例化成Hashtable对象。这个Hashtable对象将用来保存HTML表单元素的名字/值对。
fields = new Hashtable();
由于已经有了分界符,接下来我们就可以开始提取出表单元素的值。具体方法是用一个while循环按行读入HttpServletRequest对象的内容,直至遇到内容结束readLine方法返回-1为止。所有的表单元素都以分界符开始,后面跟上“Content-Disposition”行,这一行由下面这些字符开始:
Content-Disposition: form-data; name=
表单元素有两种类型:文件,非文件(普通的表单元素,如TEXT或者HIDDEN元素)。这两种表单元素的区别在于文件元素包含字符串“filename="filename"”。由此,我们可以利用该信息把文件和非文件的表单输入元素区别开来,代码如下:
if (newLine.startsWith("Content-Disposition: form-data; name="")) {
if (newLine.indexOf("filename="") != -1) {
// 文件型表单输入元素
// 这里加上提取文件的代码
. . .
}
else {
// 普通表单输入元素
// 这里加上提取表单元素的代码
. . .
}
}

现在,我们首先来看看提取文件内容的代码。
文件路径包含在“Content-Disposition”的后面。为提取文件路径和文件名字,doUpload方法调用了setFilename私有方法。setFilename方法提取出文件路径和文件名字信息,然后把它们赋值给filepath和filename域。调用setFilename方法之后,filename域应该不再是null。如果此时filename域仍旧是null,则说明遇到了问题,doUpload方法直接返回。
if (filename==null)
return;
“Content-Disposition”行之后的下一行是内容类型行。因此,doUpload方法接着调用readLine方法,然后调用setContentType私有方法。setContentType方法和setFilename方法相似,它从原始字节数据中提取出上载文件的内容类型并保存到contentType域。
紧接内容类型行的下一行是空行,因此程序再调用了一次readLine方法。
i = in.readLine(line, 0, 128);
接下来开始了真正的文件内容。我们先应该做好通过PrintWriter对象把文件写入磁盘的准备。
PrintWriter pw = new PrintWriter(new BufferedWriter(
new FileWriter(
( savePath==null? "" : savePath ) + filename
)));
上载文件保存到哪个位置取决于savePath域是否已经设置。如果savePath域没有设置,它的值是null,则文件将被保存到默认目录;如果savePath域已经设置,它的值不是null,则上载的文件被保存到它所指定的目录。
然后我们就可以提取文件的内容。具体方法是使用while循环,每次循环读入一行内容并通过PrintWriter的输出方法把它写入磁盘。但我们知道,文件的最后一行包含两个回车换行符号,所以保存到磁盘的字节数据不应该包含这两个字符。因此,如果读入的行不是文件的最后一行,我们把所有读到的字节数据写入磁盘;如果读入的行已经是文件的最后一行,写入磁盘的字节数据要减去最后两个字符。
然而,我们并不知道文件的大小,我们只知道紧接文件内容的下一行又是一个分界符;或者,如果文件是最后一个HTML表单元素,接下来的一行是分界符加上两个短划线字符。因此,只要检查下一行内容是否是分界符,我们就知道了何时应该结束while循环。这就是前面说分界符很重要的原因,在这里我们必须用到分界符。
虽然我们可以读取下一行内容然后用startsWith方法检查它是否是一个分界符,然而,由于字符串操作的开销非常大,为了减少字符串操作,我们比较readLine读入的字节数组的长度。后者应该等于boundaryLength + 2;或者,如果它是HttpServletRequest对象中的最后一行,由于多出了最后两个短划线字符,它应该等于boundaryLength + 4。由于一行内容即使不是分界符也可以和分界符一样长,当长度匹配之后我们又将它与分界符比较。这就是前面提到boundaryLength很重要的原因了。
整个处理过程的实现代码如下:
while (i != -1 && !newLine.startsWith(boundary)) {
i = in.readLine(line, 0, 128);
if ((i==boundaryLength+2 || i==boundaryLength+4)
&& (new String(line, 0, i).startsWith(boundary)))
pw.print(newLine.substring(0, newLine.length()-2));
else
pw.print(newLine);
newLine = new String(line, 0, i);
}
把文件内容保存到磁盘之后,我们关闭了PrintWriter。
pw.close();
非文件的表单元素也可以用类似的方法提取。不同之处在于,此时我们不再把数据写入磁盘,而是把名字-值对保存到Dictionary对象。
fields.put(fieldName, fieldValue.toString());
byte[] line = new byte[128];

用JavaBean实现文件上载(四)方法

[ 1 ]
用JavaBean实现文件上载(四)方法 num

打印本页 关闭

关于我们版权声明本站导航友情连结作品演示 TOP↑