分享
 
 
 

自己编写JAVA环境下的文件上传组件

王朝java/jsp·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

自己编写JAVA环境下的文件上传组件

上传文件是经常用到的,B/S环境下的文件上传原理其实和带附件的Email一样,HTTP数据流

由标志性的数据加上文件数据组成,你只要得到数据流将其标志性数据去掉,剩下的就是你

的数据文件了,在将其写成文件就完成了上传。

下面我们分布说明:

1.上传文件的静态页面,我们一定要确认method="post" enctype="multipart/form-data"

为什么就不要说了吧。

<%@ page contentType="text/html; charset=GBK" %>

<html>

<head>

<title> browsefile </title>

</head>

<body>

<h1> test2 </h1>

<FORM method="post" enctype="multipart/form-data" action="iFileUpload.jsp" >

<INPUT name="filea" type="file"><BR>

<INPUT name="btnval" type="submit" value="上载">

<INPUT type="reset" value="重置">

</FORM>

</body>

</html>

客户端上传后,服务器端的数据流头尾部格式如下,这里上传了一个Word文档

我们看看数据流的头部:

-----------------------------7d22f821706e0Content-Disposition: form-data;

name="filea"; filename="C:\工作流管理系统总体设计.doc"Content-Type:

application/msword

邢唷??...... (注意这里是数据文件开始的地方)

....................................

尾部标志:

-----------------------------7d22f821706e0Content-Disposition: form-data;

name="btnval"

上载-----------------------------7d22f821706e0--

所以去掉头尾部标志性数据我们就得到上传的文件数据了。

下面我们看看处理上传的Bean:uploadBean 首先得到初始化Bean得到上下文环境:

public final void initialize(PageContext pageContext)

throws ServletException

{

m_application = pageContext.getServletContext();

m_request = (HttpServletRequest)pageContext.getRequest();

m_response = (HttpServletResponse)pageContext.getResponse();

}

将数据流写到一个BYTES数组中,数组大小就是REQUEST流的大小。

m_totalBytes = m_request.getContentLength();

m_binArray = new byte[m_totalBytes];

for(; totalRead < m_totalBytes; totalRead += readBytes)

try

{

m_request.getInputStream();

readBytes = m_request.getInputStream().read(m_binArray, totalRead, m_totalBytes - totalRead);

}

catch(Exception e)

{

System.out.println(" Unable to upload data .");

e.printStackTrace();

}

2。下面就开始处理BYTES数组

以前我见到有网友的作法将m_binArray直接转化成String,然后利用String的方法去掉标志

位数据

String newstr=new String(m_binArray);

这一方法我试过了,是行不通的,我不知道它们测试过程序没有,对于上传文本文件应该没问题

如果上传的是WORD文档或者图片等二进制文件,进行转化成字符串的时候数据就会有丢失,我想

可能是因为编码的原因造成的,所以不能直接转换。

正确的方法是将字节数组的每一位转化成CHAR或判断ASCII码值来判断头尾标志为数据:

for(; !found && m_currentIndex < m_totalBytes; m_currentIndex++)

{

if(m_binArray[m_currentIndex] == 13)

found = true;

else

m_boundary = m_boundary + (char)m_binArray[m_currentIndex];

}

if(m_currentIndex == 1)

return;

m_currentIndex++;

do

{

if(m_currentIndex >= m_totalBytes)

break;

dataHeader = getDataHeader();

System.out.println(dataHeader);

m_currentIndex = m_currentIndex + 2;

isFile = dataHeader.indexOf("filename") > 0;

getDataSection();

if(isFile)

{

////

System.out.println("----->m_startData:"+m_startData);

System.out.println("----->m_endData:"+m_endData);

try

{

fileout = new FileOutputStream("c:\\test11.doc");

fileout.write(m_binArray,m_startData,m_endData-m_startData+1);

fileout2 = new FileOutputStream("c:\\test00.doc");

fileout2.write(m_binArray);

}

catch(Exception e)

{

System.out.println(" Unable to write data to test file .");

e.printStackTrace();

}

finally

{

try

{

fileout.close();

fileout2.close();

}

catch(Exception e)

{

e.printStackTrace();

}

}

}

private String getDataHeader()

{

int start = m_currentIndex;

int end = 0;

int len = 0;

boolean found = false;

while(!found)

if(m_binArray[m_currentIndex] == 13 && m_binArray[m_currentIndex + 2] == 13)

{

found = true;

end = m_currentIndex - 1;

m_currentIndex = m_currentIndex + 2;

}

else

{

m_currentIndex++;

}

String dataHeader = new String(m_binArray, start, (end - start) + 1);

return dataHeader;

}

private void getDataSection()

{

boolean found = false;

String dataHeader = new String();

int searchPos = m_currentIndex;

int keyPos = 0;

int boundaryLen = m_boundary.length();

m_startData = m_currentIndex;

m_endData = 0;

do

{

if(searchPos >= m_totalBytes)

break;

if(m_binArray[searchPos] == (byte)m_boundary.charAt(keyPos))

{

if(keyPos == boundaryLen - 1)

{

m_endData = ((searchPos - boundaryLen) + 1) - 3;

break;

}

searchPos++;

keyPos++;

}

else

{

searchPos++;

keyPos = 0;

}

}

while(true);

m_currentIndex = m_endData + boundaryLen + 3;

}

m_currentIndex为当前字节数组的指针位置,先得到HEADER数据,见方法getDataHeader()

然后在得到文件数据开始的指针位置和SIZE,见方法getDataSection()

然后,将数据流写到文件里:

fileout.write(m_binArray,m_startData,m_endData-m_startData+1);

就得到了完整的数据文件,上面test00.doc 和 test11.doc 是去掉标志数据前后的数据流

分别写成的文件,大家用二进制查看程序可看出其中的差别。

以上getDataHeader(),getDataSection()是我参考了SMARTUPLOAD的实现原理,

其中分析标志数据位的方法稍有复杂,网友可自己去分析。程序在TOMCAT下测试通过,

上传WORD文档和图片都没问题。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有