--------------=struts1.2 批量自动上传,批量下载(无组件)=--------------

第一章节:自动上传非主流,IC,IP,IQ卡统统告诉我密码----上传方法总结

前段时间做一个上传模块,很是上火。要求根据解析来的文件路径自动上传。有点IC,IP,IQ卡统统告诉我密码的感觉。换言之,就是自动上传。

在这要感谢我的良师益友许老师,没有他的热情帮助这个任务直接完不成!

    话说上传,不管你是asp,.net ,jsp,php你只要跟微软同学打交道。我艹,一般都是file标签,然后配合一系列的组件来上传。你可能说你是struts,俺不用file标签。老师,其实那玩意解析过了,也是对应<input type="file">标签。人家微软为了安全让你点击浏览--->选文件--->文件路径付给这个file标签的value。 这里补充说明一下,这个value是只读了。一般情况下,你赋值不好使,你可能要说通过shell,那个动态多文件上传,他就不好使了。

闲话少说,先说上传分类(传统套路少林拳)file标签+ 组件这个网上很多。咱不说了。不走寻常路的美特斯邦威说:老师有没有不用file标签滴  。天空中传来一个朦胧地声音,乾坤大挪移舶来品不用file标签,类似QQ的信箱附件添加滴那些一般都是需要客户端控件(ActiveX)类似插件,插了进来(问什么要插呢)。这个太深奥,初学者内功不是很深厚的不容易掌握(九阴真经)。

再有就是咱这个思路了ADOstream (绝对滴凌波微步)。用这个的思路大致上说一下

创建xml,将要上传的文件内容用adostream来读(字节流)插到xml的节点上。然后ajax方式发送服务器端,解析这个xml 读节点内容。写到指定路径下,写文件。

故事梗概大概到这也就结束了,咱下面来看看赠品:(struts1.2 +adostream+xml+jsp+...)

读文件内容,获得字节流放在xml,ajax发送后台

function  filepost(jid,pnm)
 { 
  //debugger;
    var FileName="";
    var tableobj = window.frames["iframe1"].document.getElementById("file_list");//获得iframe中表的句柄
    var ado  =  new   ActiveXObject("ADODB.Stream");//创建ADO-stream   对象
    ado.Type=1; // 1=adTypeBinary ado;
   // ado.Type = 2;
    var xml_dom   =   new   ActiveXObject("MSXML2.DOMDocument"); //创建包含默认头信息和根节点的 XML文档       
    xml_dom.loadXML('<?xml   version="1.0"   ?>   <root/>');  
    xml_dom.documentElement.setAttribute("xmlns:dt",   "urn:schemas-microsoft-com:datatypes");//指定数据类型
    var tal="";
    for( i=1; i<tableobj.rows.length; i++)
    {
   if(tableobj.rows[i].cells[1].innerText!="")
   {
    PathName = tableobj.rows[i].cells[1].innerText ;
      var strArray=new Array();
    strArray=PathName.split("//") ;
    FileName = strArray[strArray.length-1] ;//获得文件名
      var fnode=xml_dom.createElement("file");//创建file节点
      xml_dom.documentElement.appendChild(fnode);
      var lastnode=xml_dom.documentElement.lastChild;
      fnode=xml_dom.createElement("name");//创建name节点
      fnode.text=FileName
      lastnode.appendChild(fnode);
      fnode=xml_dom.createElement("content");//创建文件内容节点
      //fnode.dataType = "string";
      fnode.dataType = "bin.base64";
      ado.Open();
      ado.LoadFromFile(PathName);
      fnode.nodeTypedValue=ado.Read(-1);//将文件内容存入XML节点
    ado.Close();
    lastnode.appendChild(fnode);
      
   }
     
    }
    //alert("xml******************"+xml_dom.xml);
  // alert("xml******************"+xml_dom)
    var   xmlhttp   =   new   ActiveXObject("Microsoft.XMLHTTP");  //   把XML文档发送到Web服务器
   // var post_url = "/batchSoftapp.do?method=fileUpLoad" ;
    var post_url = "/batchSoftapp.do?method=fileUpLoad&currJobid="+ jid+"&projectName="+pnm;
   alert("post_url======="+post_url);
    xmlhttp.open("POST",post_url,false);
    xmlhttp.send(xml_dom);
   //xmlhttp.send(xml_dom.xml); 
 }

后台接收,解析部分

BatchSoftappForm batchform = (BatchSoftappForm)form;
   System.out.println("文件上传执行");
   System.out.println("fileUpLoad");
    PrintWriter out = response.getWriter();
    SAXBuilder builder = new SAXBuilder();
    Document requestDoc = null;// 输入XML DOC
    Document responseDoc = null;// 输出XML DOC
    XMLOutputter xmlOut = new XMLOutputter(Format.getPrettyFormat().setEncoding("utf-8"));
   
    String dir = this.getServlet().getServletContext().getRealPath("uploadfile")+"
//"+request.getParameter("projectName")+"//"+request.getParameter("currJobid");
    System.out.println("新建服务器端文件保存路径==="+dir);
    if(request.getParameter("currJobid")!=null)
    {
        File mdkFile = new File(dir);
     if(!mdkFile.exists()){
      mdkFile.mkdirs();
     }
    }

    System.out.println("写文件内容");

    try {
      
        requestDoc = builder.build(request.getInputStream());//由XML文档的输入流得到一个org.w3c.dom.Document对象
        Element root = requestDoc.getRootElement();
        List list = root.getChildren("file");// 取名字为file的所有元素 
           System.out.println("listSize : "+list.size());  
           Iterator it = list.iterator();  
           while (it.hasNext()) {  
               Element e = (Element) it.next();
               byte[] b = new sun.misc.BASE64Decoder().decodeBuffer(e.getChildText("content")); //
解码很关键
               ByteArrayInputStream  inStream=new ByteArrayInputStream(b);
               FileOutputStream fs=new FileOutputStream(dir+"/"+e.getChildText("name"));
               int bytesum=0;
               int byteread=0;
               while ((byteread=inStream.read(b))!=-1){ 
                bytesum+=byteread;
                fs.write(b,0,byteread);
                }
               System.out.println("filename=="+e.getChildText("name")+"文件保存路径=="+dir);
                fs.close();
                inStream.close();               
           }
      }

后台处理xml有很多方法,咱用jdom方式。这个直接使用不用插包。

后台需要导的类有

import java.io.* ;
import org.jdom.*;
import org.jdom.input.*;
import org.jdom.output.*;
import sun.misc.BASE64Decoder;//解码滴
import sun.misc.BASE64Encoder;

片场花絮:

开发时注意(防火防蚊虫)input标签,俺不管你是hidden,box,text滴,一不高兴MSDN就骂,咱浏览器发送时你可能hidden能传个9M的东西,到了web服务器,人家对post上来的值有限制,谢谢。tomcat 2M默认滴。服务器限制咱可以弄,给他弄大,可是服务器端request.get***只能得到100K左右。换言之,html  Form中 标签能传值的大小是100K左右(单个滴eg<input type="text">100k <input type ="hidden">又是100K并不是这个form只能传100k

再有就是struts中动态标签添加的问题。比如动态上传时,我最初的思路是用hidden来存放JavaScript读取的文件内容。文件数目不定用动态添加 hidden  name="a1".......ai的方式,Formbean不好操作,这时完全可以定义同名的hidden标签在FormBean中定义一个数组来存放。后台遍历下for(***)就能取到。

再有就是post get发送请求的问题。你可能整天用,但是其中的原理可能您也不一定能说的很明白。来,咱一起来给他脱,post传值对应http报文的body部分。这部分不限制你的大小,你有多少他能传多少。(类似老子看到某东西时的感叹,吞吐万物啊),get对应http报文的head部,他这块有限制。咱一般的网址请求(url)? 后边的那些,一般是1K左右,就是受这个限制地。当然你也可以调web服务器上的http报文的head 大小。来传输更大的报文头。我试过一下,调到1M左右,我艹,页面加载大约需要5分钟。你想想,5分钟啊!由此可见有的东西太大就不好使。

 

第二章节:无组件批量下载

再一次感谢感谢老师,在他的热情帮助还耐心讲解下,struts1.2框架的批量下载(无组件)终于新鲜出炉了。

需求:网页上复选框选择要下载的文件(类似Mp3批量下载,只不过人家的大多数是组件滴),然后下载选中的文件。

设计思路:前台jsp页面form 传参传文件路径,多文件的话,将这些文件路径用分隔符拼接,后台分割这些文件路径,然后将这些文件路径下的文件打包,然后在下载。总体来说三步走,上传文件(路径),文件打包,下载。

思路出来了,代码如下仅供参考:

要下载作业下文件目录显示:

public ActionForward JobIdFileList(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) {
  System.out.println("zyFileList");
  Userinfo userinfo =(Userinfo)request.getSession().getAttribute("userinfo");
//  if(userinfo == null){
//   return null;
//  }
  String strpath = this.getServlet().getServletContext().getRealPath("uploadfile")+"
//"+request.getParameter("projectName")+"//"+request.getParameter("JobId");
  System.out.println("dir============="+strpath);
  //ArrayList<String> filelist = new ArrayList<String>();
  Map<String,Long> formatFileMap = new HashMap<String,Long>();
   File  dir = new File(strpath);//通过路径来创建一个file实例
   File[] files = dir.listFiles();//返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件
  // System.out.println(""+files.length);
   if (files==null)
    System.out.println("该作业ID下文件为空") ;  
   for (int i=0;i<files.length;i++){
    formatFileMap.put(files[i].toString(),files[i].length() );
   }
   request.setAttribute("fileMap", formatFileMap);  
  return mapping.findForward("zyFileList");
 } 

前台作业选择页面

<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
<%@ page import="java.io.*" %>
<%@ page import="java.util.*" %>


  <html:form action="/batchSoftapp.do?method=fileDownLoad"  method="post">
 <div id="box_all">
  <div id="box_left">
     <table style="width:800px;"  class="tableList" border="1" cellspacing="0" cellpadding="0" style="table-layout: fixed;"  align="center" >
      <tr style="background-color:#D7F2F4" align="center">
     <td  class="fixhead"  width="8%">选择</td>
     <td  class="fixhead" width="75%" >文件名</td>
     <td  class="fixhead" width="17%" >文件大小</td>
      </tr>
      <%
         Map map = (Map)request.getAttribute("fileMap");
       //System.out.println("map.size"+map.size());
       if(map!=null){    
        Iterator   keyValuePairs = map.keySet().iterator();
        while(keyValuePairs.hasNext())   { 
         String filepath = (String)keyValuePairs.next();
         String filename =filepath.substring(filepath.lastIndexOf("
//")+1);
         //System.out.println();
         Long filelength=(Long)map.get(filepath);  
      %>
      <tr>
     <td><input name="filechecked" id="filechecked" type="checkbox" checked= "true"  align="center" value="<%=filename %>,<%=filepath %>"> </td>
     <td><%=filename %> </td> 
     <td><%=filelength%>字节 </td>
      </tr>
      <% }
       }
      %>
     </table>
  </div>
  <div id="box_right" align="center">  
   <input type="button" value="全选" title="选择下载的文件" οnclick="SelectAll(this.form)">
   <input type="button" value="反选" title="反向选择下载的文件" οnclick="TurnOver(this.form)" > 
   <input type="button" value="下载" title="下载选中的文件" οnclick="DownLodSelected(this.form)">
   <input type="button" value="返回" title="返回作业ID列表页面" οnclick="window.history.back()">  
  </div>
  <input type="hidden" name="filenames" id="filenames" >
  <input type="hidden" name="filepaths"  >
 </div>
   </html:form>
  </body>
  </html:html>
<script type="text/javascript">
 /**
  * 功能:复选框全选
  * 参数:form对象
  * 思路:
  * 作者:   */
 function SelectAll(oForm){
  for(var i=0;i<oForm.filechecked.length;i++){
   oForm.filechecked[i].checked=true;   
  } 
 }
  /**
  * 功能:复选框反选
  * 参数:form对象
  * 思路:
  * 作者:   */
 function TurnOver(oForm){
  for(var i=0;i<oForm.filechecked.length;i++){   
   oForm.filechecked[i].checked=!oForm.filechecked[i].checked;      
  } 
 }
 /**
  * 功能:下载文件列表实现
  * 参数:form对象
  * 思路:
  * 作者:   */
 function DownLodSelected(oForm){
  if(confirm("因需要在服务端动态打包,需要时间比较长,是否继续批量下载?"))
  {//debugger;
   var arrDownloadList = [];    
   for(var i=0;i<document.getElementsByName("filechecked").length;i++)
   { 
    if(document.getElementsByName("filechecked")[i].checked==true)
    {
     if(arrDownloadList.length==0){
                        arrDownloadList[0] = document.getElementsByName("filechecked").value;
                    }
     arrDownloadList[arrDownloadList.length] = document.getElementsByName("filechecked")[i].value;     
    }
   } 
   if(arrDownloadList.length>0){
   var temp=[];
   var filenames="";
   var filepaths="";
   for(var i=1;i<arrDownloadList.length;i++){
   //alert("=========="+arrDownloadList[i])
    temp = arrDownloadList[i].split(",")
    if(filenames==""&&filepaths==""){
     filenames=temp[0];
     filepaths=temp[1];
    }else{
     filenames=filenames+"|"+temp[0];
     filepaths=filepaths+"|"+temp[1];     
    }
   }
   //alert("filenames==="+filenames);
   //alert("filepaths==="+filepaths);
    downloadFile(filenames,filepaths);     
  }else{
   alert("还没有选中下载项");   
  }  
  }

 }
 /** 
 *功能: 文件下载
 *思路:
 *參數說明:复选框选中的要下载的文件名拼接,以及文件路径拼接
    *返回值  :
    *作者:    */ 
 function  downloadFile(filenames,filepaths){
    
  //location.href=encodeURI(encodeURI("/batchSoftapp.do?method=fileDownLoad&filenames="+filenames+"&filepaths="+filepaths));
  document.forms[0].filenames.value=filenames;
  document.forms[0].filepaths.value=filepaths;
  document.forms[0].submit();    
 }
</script> 

后台Action 部分关键部分

   String   filenames;
  String   filepaths;
  String[] filenameArray = null;
  String[] filepathArray = null;
  String   filename;
  String   filepath;
  SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
  filenames=request.getParameter("filenames");
  filepaths=request.getParameter("filepaths");
  System.out.println("filenames==================="+filenames);
  System.out.println("filepaths==================="+filepaths);
  filenameArray = filenames.split("
//|");//
传入要进行打包的所有文件
  filepathArray = filepaths.split("
//|");//传入要进行打包的所有文件路径
  //filename="批量打包下载.zip";
  filename=format.format(new Date())+".zip";
  //String requestip =ServletActionContext.getRequest().getLocalAddr();
  System.out.println("*******************"+this.getServlet().getServletContext().getRealPath("/uploadfile/temp"));
  //filepath = "c://批量打包下载.zip";  //产生的压缩文件路径和名字
  filepath = this.getServlet().getServletContext().getRealPath("/uploadfile/temp")+"
//"+filename;
  File tempfile = null;
  if(filenameArray!= null&&filepathArray!= null&&filenameArray.length>0 && filenameArray.length==filepathArray.length  ){
   try{
    File f=new File(filepath);
     f.createNewFile();
     ZipOutputStream out = new ZipOutputStream(new FileOutputStream(f));
     out.putNextEntry(new ZipEntry("/"));
     for(int i=0;i<filepathArray.length;i++){
      //FileInputStream In = new FileInputStream(this.getServlet().getServletContext().getRealPath(filepathArray[i]));
     // System.out.println("路径"+this.getServlet().getServletContext().getRealPath(filepathArray[i]));
      FileInputStream In = new FileInputStream(filepathArray[i]);
      out.putNextEntry(new ZipEntry(filenameArray[i])); //开始写入新的 ZIP 文件条目并将流定位到条目数据的开始处     
      int b;
      while((b = In.read()) != -1) {
       out.write(b);
      }
      In.close();
     }    
     out.flush();
     out.close();
     tempfile = new File(filepath);
    String downFileNm=tempfile.getName();//取得要打包后要下载的文件的文件名(文件打包后的压缩文件)
    System.out.println("downFileNm===="+downFileNm);
    System.out.println("downFileNm.length===="+tempfile.length());
    //以流的形式下载文件
    InputStream fis = new BufferedInputStream(new FileInputStream(filepath));//获得目标下载文件输入流
    byte[] buffer = new byte[fis.available()];
    fis.read(buffer);
    fis.close();
    response.reset();//清空response
    // 设置response的Header
    //response.addHeader("Content-Disposition", "attachment;filename=" + new String(downFileNm.getBytes()));
    //是下载的那个文件另存为的时候的名字
    response.addHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(downFileNm,"UTF-8"));
    response.addHeader("Content-Length", "" + tempfile.length());
    OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
    response.setContentType("application/octet-stream");//设置响应的MIME类型
    toClient.write(buffer);//你写的是buffer,也就是fis,也就是filepath这里对应的zip文件。这个是uuid.zip的话,上面的filename可以是abcd.zip
    toClient.flush();
    toClient.close();
    
   }catch(IOException e) {
    System.out.println("抛出异常:"+e.getMessage()+"   "+"压缩文件出错!!");

   }finally{
    if(tempfile.exists())
    {
     
     tempfile.delete();
     if(tempfile.exists())
     {
      System.out.println("---------删除临时文件失败-----------");

     }else
     {
      System.out.println("------删除打包产生的临时文件------");
     }
    }
    
   }
   
  }
  else{
   System.out.println("请求下载文件的路径或者文件名存在问题");
  }
  
  //return null ;

最后要说的有这么几点一个是参数中含有汉字的问题,tomcat中相关文件没有配置的话,解决后台乱码有这么两种方式,get方式发送时,前台jsp页面两次encodeURI(encodeURI("url跳转地址串"))后台再解码即可。再有就是post方式发送,将要传递的参数放置在input hidden的标签中,后台直接request.getParameter("参数名")也可,强烈推荐后面的处理方式。

再有就是打包压缩的文件名这一块,为了预防同时刻,不同用户操作该文件下载,最好使用UUID号的方式命名。

      再一次感谢许老师。

 

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值