上传图片之全过程

     我最近在做一个宠物网站, 主打产品是“狗狗”。其中我在添加狗狗时需要添加狗狗的照片, 刚开始接触时觉得这似乎不成什么问题, 因为之前有做过将图片直接插入数据库的练习, 在oracle中将图片相应的字段设置为blob然后再进行流的读写即可。但是当开始真正做项目时才意识到了这真是一个难题, 到现在我还没有试验成功, 将整个过程记录一下:

   1、 首先考虑直接往数据库中插入图片,参考了很多资料前后忙了将近两个小时 后来放弃了, 一则是这样子操作较复杂,而也是太占数据库容量了读取数据时影响速度。

   2、  联想到自己前几天用JS实现的一个关于“图片预览”的东东,突然觉得保存图片的存储路径即可以了, 取图片时取得图片对应的路径然后再将路径赋给图片的src去实现。 接着便马上开始试验,试验成功,正当为自己的灵机一动兴奋时突然又想到了自己只是在本机上实现了, 我并没有考虑将图片存进服务器。

  3、  关于如何上传图片到服务器于我而言又是一个难题, 之前不知有组件这种方式,上网搜了很多,感觉那些解决方案都较难。无意中发现一个帖子说可以用组件来实现, 于是便立马从网上下载了一个jsp smartupload组件来使用。 参考这示例代码上传照片成功了, ^_^  ^_^  正当再次欢呼时又面临新的问题了, 因为我上传图片使用的是  

<FORM   ENCTYPE="multipart/form-data"   action="get.jsp">  
  <input   type="hidden"   value="aaa">  
  </form>这种形式的, 这样子我在get.jsp页面中就取不到hidden表单中的值了; 而当我将ENCTYPE="multipart/form-data"去掉时虽然能够取得hidden文本域的值但又实现不了上传....

        晕, 郁闷,虽然我将上传于获取普通文本域的值分成两个form表单来做是可以的, 但是我就想放一个表单里来做该怎么办呀?  ————我为了不拖延项目完工的时间只好做成两个表单。

    ———先记录一下网上搜索到的相关资料:

      a、   BinaryRead   方法用于读取作为   POST   请求的一部分从客户端发出的未加工数据。此方法用于在底层访问数据,与此相反,Request.Form   集合用于查看在公告请求中发送的表格数据。一旦调用了   BinaryRead,则引用   Request.Form   集合中的任何变量都将导致错误发生。反之,一旦引用了   Request.Form   集合中的一个变量,则调用   BinaryWrite   也将导致错误发生。请记住,如果在访问   Request   集合中的变量时未指定该变量属于哪一个子集,将搜索   Request.Form   集合并强制使用上述规则。  
   
  那么,如何在表单的   enctype   属性为   multipart/form-data   的情况下取得表单元素值呢?思路很简单:BinaryRead方法对当前输入流进行指定字节数的二进制读取   ->   借助   RecordSet   的   AppendChunk   方法将二进制流转化成文本   ->   用正则分析出文本中包含的元素名及元素值  
   
  Dim   binData,   intSize,   objFormValue  
  intSize   =   Request.TotalBytes  
  binData   =   Request.BinaryRead(intSize)  
  Set   objFormValue   =   FormValue(binData,   intSize)  
  Const   adLongVarChar   =   201  
  Dim   RS,   strData,   strTmp,   objRegExp,   objDictReg,   objMatches,   Match  
  Set   RS   =   CreateObject("ADODB.Recordset")  
  RS.Fields.Append   "mBinary",   adLongVarChar,   intSize  
  RS.Open  
  RS.AddNew  
    RS("mBinary").AppendChunk(binData)  
  RS.Update  
  strData   =   RS("mBinary").Value  
  RS.Close  
  Set   RS   =   Nothing  
   
  现在   strData   已经是包含表单值的字符串了

 

   b、    同时有上传和一般输入,enctype也是multipart/form-data,所以这里是对的,问题在于server端如何处理请求。

          主要是接收页面的处理.贴个例子给你看看  
   
  我的代码也贴一下  
  try  
                  {  
                          response.setContentType(CONTENT_TYPE);  
                          PrintWriter   out   =   response.getWriter();  
                          String   server_path=request.getRealPath("/");  
                          String   saveDirectory   =server_path+"/file_pic/";  
                          String   tmpDirectory   =   "c://";  
                          int   maxPostSize   =   1024   *   1024;  
                          boolean   is_legal_file=false;  
                          String   FileDescription   =   null;  
                          String   FileName   =   null;  
                          long   FileSize   =   0;  
                          String   ContentType   =   null;  
                          int   count   =   0   ;  
   
                          java.util.Vector   text   =   new   java.util.Vector();//存放非文件域信息  
   
                          java.util.Vector   vector_file   =   new   java.util.Vector();//存放文件域信息  
   
                          DiskFileUpload   upload   =   new   DiskFileUpload();//初始化上传组件  
   
                          upload.setSizeThreshold(4096);//设置文件流大小  
   
                          upload.setSizeMax(maxPostSize);//设置最大文件,超过则临时存放到:tmpDirectory  
   
                          upload.setRepositoryPath(tmpDirectory);//设置临时存放点  
   
                          List     items   =   upload.parseRequest(request);//取得request  
   
                          Iterator   iter   =   items.iterator();//初始化  
                          int   file_no=0;  
                          int   tmp   =   0;  
                          FileItem   tmpItem   =   null;  
  //-------------------------------------------------          
                  while   (iter.hasNext())//表单有多个域  
  //-------------------------------------------------            
                {  
                                  tmp++;  
  //-------------------------------------------------  
                                  FileItem   item   =   (FileItem)   iter.next();  
  //-------------------------------------------------  
                                  if   (item.isFormField())//如果是非文件域信息  
                                  {  
                                          FileDescription   =   item.getString();//取得非文件域信息,皆为字符串类型  
                                          text.addElement(FileDescription);//加入到存放非文件域信息之向量  
                                  }  
                                  else   //如果是文件域信息  
                                  {  
                                          file_no++;  
                                          FileName   =   item.getName();  
                                          try   //因为不同的浏览器会造成   path   +   filename,   有些则只有   filename  
                                          {  
                                                  //   for   wintel   platform  
                                                  FileName   =   FileName.substring(FileName.lastIndexOf("//")+1);//取得档案名称  
                                                  //   for   unix-like   platform  
                                                  FileName   =   FileName.substring(FileName.lastIndexOf("/")+1);//取得档案名称  
                                          }  
                                          catch   (Exception   ex)  
                                          {  
                                                  System.out.println("取文件名出错:"+ex);  
                                          }  
                                          ContentType   =   item.getContentType();//取得档案类型  
                                          FileSize   =   item.getSize();//取得档案大小  
                                          tmpItem   =   item;  
   
                                          try   //   將檔案寫入存檔目錄  
                                          {  
                                                  //转换文件名  
                                                  java.text.SimpleDateFormat   formatter   =   new   java.text.SimpleDateFormat("yyyyMMddhhmmss");  
                                                  java.util.Date   currentTime_1   =   new   java.util.Date();  
                                                  String   ss=formatter.format(currentTime_1);  
                                                  String   FileName_houzhui=FileName.substring(FileName.lastIndexOf("."));  
                                                  FileName=ss+file_no+FileName_houzhui;  
                                                  vector_file.addElement(FileName);  
                                                  File   uploadedFile   =   new   File(saveDirectory   +   FileName);  
                                                  tmpItem.write(uploadedFile);  
                                          }  
                                          catch(Exception   ex)  
                                          {  
                                                  System.out.println("保存文件出错:"+ex);  
                                                  System.out.println("错误位置:/servlet/com.sxztb.upload.uploadServlet");  
                                          }  
                                  }  
                          }  
   
                          //转到写文件类,完成写文件  
                          try  
                          {  
                          upload_write_file_servlet   tody_log   =   new   upload_write_file_servlet(server_path);  
   
                          tody_log.log_wite((String)text.elementAt(0),(String)text.elementAt(1),(String)text.elementAt(2),(String)text.elementAt(3),(String)vector_file.elementAt(0),(String)vector_file.elementAt(1),(String)vector_file.elementAt(2));  
                          }  
                          catch   (Exception   e)  
                          {  
                                  System.out.println("生成JSP文件出现错误!"+e);  
                                  System.out.println("错误位置:/servlet/com.sxztb.upload.uploadServlet");  
                          }  
                          //写文件结束,转到相应目录  
                          getServletContext().getRequestDispatcher("/news/").forward(request,response);  
                  }  
                  catch(Exception   e)  
                  {  
                          System.out.println("/servlet/com.sxztb.upload.uploadServlet出错"+e);  
                  }  
  *******************************************************************************************************************  
   
  上述的取得request中的表单中的每一个元素,可以不用迭代器   iterator.  
  List类中的List.size()取得多少个元素,  
  List类中的List.get(i)取得某个元素,  
  以上的这几行代码可以这样改!:  
  -------------------------------------------------          
                  while   (iter.hasNext())//表单有多个域  
  -------------------------------------------------            
               
  改:  
                  for(int   i=0;i<items.size();i++)       //items是List对象  
  -------------------------------------------------  
                                  FileItem   item   =   (FileItem)   iter.next();  
  -------------------------------------------------  
  改  
                                  FileItem   item   =   (FileItem)   items.get(i);

   c

     我一般是这样做的先在申明一个处理上传文件的javaBean  
  <jsp:useBean   id="myUpload"   scope="page"   class="xiaoxiang.fileUpload.upBean"   />  
  然后通过下面的方法可取另外的参数值  
  myUpload.getRequest().getParameter("参数名或控件名")  
   
  这个方法绝对OK  

   d、  还得靠自己,总算找到办法了,用下面方法可以取道文本等控件的值,只不过执行下面代码后request变量里面为空了(其值付给了List),如果取file控件的值的操作在后面(在同一地点就没有这种问题了)就不能用request了,而应该直接用List变量items   或   Iterator变量itr  
              List   items   =   null;  
                                try{  
                  DiskFileUpload   upload   =   new   DiskFileUpload();  
                  items   =   upload.parseRequest(request);  
                  Iterator   itr   =   items.iterator();  
                  while(itr.hasNext())   {  
                  FileItem   item   =   (FileItem)   itr.next();  
                  if(item.isFormField())   {  
                  String   fieldName   =   item.getFieldName();  
                  if(fieldName.equals("txtContentsJ")){  
                                  //内容(日本版)  
                  reqContentsJ   =   item.getString();  
                  }else   if(fieldName.equals("txtContentsE")){  
                                  //内容(英語版)  
                  reqContentsE   =   item.getString();  
                  }  
                  }  
                  }  
   
                  }catch(Exception   e)   {  
                      logger.error("Exception:"   +   e);  
                  }  
 

 4、 3.c的方法既简单又可行, 但是当解决了此问题时又引发了一个新的问题那就是: 由于图片都是由客户端上传到服务器的, 那么我如何保证即使上传了同名的照片而以前的照片不被覆盖呢?

          我想了一下, 觉得应该将这个存入服务器图片的路径与某项带有唯一性质的属性进行绑定。 上网搜索了一下: 用数据库记录下文件名,但保存的时候是系统生成的文件名,如表的ID,这样就实现了你的要求。显示的时候用数据库的文件名,替代实际的文件名。
   ^_^  ^_^  我也是这么想的, 现在正打算去试验。

 

    ———— 补充之 ENCTYPE="multipart/form-data"什么意思???

   表单元素中的   enctype   属性规定了传递给服务器的表数据集编码的内容类型。enctype   属性的默认值是“application/x-www-form-urlencoded”,但当向服务器传送大量文本、包含非ASCII字符或二进制数的数据时,这个默认类型就不能胜任hq了。这时,文件上载提交表单时应使用“multipart/form-data”内容类型。 也即以流的方式上传数据,用于上传文件数据。

      ENCTYPE不是单独设置的属性,它与method配饰使用,只有当method时post时ENCTYPE的设置才显得有意义。

     ————什么是MIME格式: Multipurpose Internet Mail Extensions
简称 MIME
多用途互联网络电子邮件格式的扩展。
用MIME关键字来区分文件编码格式文件种类(包括多媒体)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值