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

本文介绍了一种在Java环境下自行编写的文件上传组件实现方法。该组件通过解析HTTP请求中的multipart/form-data格式数据,准确地获取并保存上传文件。文章详细解释了如何从请求流中去除标志数据,并将剩余部分写入文件。
自己编写JAVA环境下的文件上传组件 (转)[@more@]

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

上传文件是经常用到的,B/S环境下的文件上传原理其实和带附件的EMail一样,HTTP数据流
由标志性的数据加上文件数据组成,你只要得到数据流将其标志性数据去掉,剩下的就是你
的数据文件了,在将其写成文件就完成了上传。

下面我们分布说明:

1.上传文件的静态页面,我们一定要确认method="post" enctype="multipart/form-data"
为什么就不要说了吧。




browsefile


test2


RM method="post" enctype="multipart/form-data" action="iFile UPLOAD. JSP" >





客户端上传后,服务器端的数据流头尾部格式如下,这里上传了一个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("-----&gtm_startData:"+m_startData);
  System.out.println("-----&gtm_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文档和图片都没问题。

 

 

 

 

 


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10752043/viewspace-993450/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10752043/viewspace-993450/

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值