| |
用javabean实现文件上载(6) 现在,我们首先来看看提取文件内容的代码。
文件路径包含在“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];
(全文完)
|
|