动态多附件上传----经典解决方案

动态多附件上传

----经典解决方案

    动态多附件上传,在目前的B/S系统中经常会遇到这方面的需求,基于开源的理念,在此我把几个解决方案做详细的介绍。目的在于提高自己的描述问题的能力,同时给遇到同样问题的朋友提供一些线索,以便节省宝贵时间。

 

上次项目是做一个**管理系统,其中有一个模块是作品发布,作品发布模块就需要实现这样一个功能:

      新建一个作品,作品包含一些基本的信息,而且要求要有一个或多个附件,每个附件又要求有作品概要(即作品附件和作品概要一一对应)。

系统要求用struts来实现。

在讨论解决方案之前,首先要了解的是。在客户端请求服务器时提交表单,表单的内容只能为String型和FormFile型(FormFile类型只有在Struts中才有),不能提交自己定义的dto对象。但是可以提交自己定义的dto中的String成员和FormFile成员。

了解了这个原理之后,我开始阐述第一种解决方案;

 

第一种解决方案:间接动态多附件上传

基本思路:定义一个ProductForm

  Class  ProductForm extends  ActionForm{

  String  pro_name;

  …….               //其他一些基本的成员变量;

 

//生成getset方法;

}

jsp页面上用相关的标签定义作品的字段;

如:<html:text property=”pro_name” />

动态多附件则用普通标签实现,没有在ProductForm中定义相应的字段。因此,Action取值也不能直接从ActionForm中取值,因为ActionForm中根本没有相应的成员。

这里给出相关代码:

Jsp部分:

<TABLE id=&apos;mytable&apos;>                                                                <tr><td>       </td>  </tr>

                                                                                    </TABLE>

                  <html:button value="添加新附件" styleClass="btn" onclick="add_Row(mytable);" property="add_newFile" />

动态添加附件域在jsp中的代码是:

var i = 0;

function add_Row(the_table)    { //动态增加一行,实际上也就是增加一个表格

          var    the_row,the_cell;  

          var    cur_rows=the_table.rows.length;

          the_row=cur_rows==null?-1:(cur_rows);

       //   var    i=the_row;    

          var    newrow=the_table.insertRow(i);//得到插入位置 

                 newrow.id = i;

          the_cell=newrow.insertCell(0);

                        the_cell.innerHTML="<table width=&apos;359&apos; border=&apos;0&apos; cellspacing=&apos;0&apos; id=&apos;table&apos;>" 

                    + "<tr>"

                    + "<td width=&apos;300&apos;><input id=&apos;<%= Constants.RES_NEW_FILE_PARAMETER_NAME%>"+i+"&apos; name=&apos;<%= Constants.RES_NEW_FILE_PARAMETER_NAME%>"+i+"&apos; type=&apos;file&apos;  οnchange=&apos;fileTypeCheck(this);&apos;  οnpaste=&apos;return   false&apos;   οnkeypress=&apos;return   false&apos;  οnkeydοwn=&apos;return  false&apos; οncοntextmenu=&apos;return  false;&apos;></td>"

                    + "<td width=&apos;55&apos;><input name=&apos;deleteRow&apos; type=&apos;button&apos; class=&apos;btn&apos; value=&apos;除此域&apos; οnclick=&apos;del("+i+");&apos;></td>"

                    + "</tr>"

                    + "<tr>"

                    + "<td ><span class=&apos;useBB&apos;>文件概要[&lt;=50]</span></td>"

                    + "<td class=&apos;style6&apos;>&nbsp;</td>"

                    + "</tr>"

                    + "<tr>"

                    + "<td>"

                    + "<textarea  name=&apos;"+i+"&apos; class=&apos;new_files_comnt&apos; οnchange=&apos;checkLength(this,100);&apos;></textarea></td>"

                    + "<td align=&apos;left&apos; valign=&apos;top&apos;>&nbsp;"

                    + "</td>"

                    + "</tr>"

                    + "</table><hr>"; 

                    i++;}           

  其中<input id=&apos;<%= Constants.RES_NEW_FILE_PARAMETER_NAME%>"+i+"&apos; name=&apos;<%= Constants.RES_NEW_FILE_PARAMETER_NAME%>"+i+"&apos; type=&apos;file&apos;  οnchange=&apos;fileTypeCheck(this);&apos;  οnpaste=&apos;return   false&apos;   οnkeypress=&apos;return false&apos;  οnkeydοwn=&apos;return  false&apos; οncοntextmenu=&apos;return  false;&apos;><textarea  name=&apos;"+i+"&apos; class=&apos;new_files_comnt&apos; οnchange=&apos;checkLength(this,100);&apos;></textarea>

中的Constants.RES_NEW_FILE_PARAMETER_NAME是在常量类Constants.java中定义的常量,每个Struts项目中都会有这个类文件,目的在于统一接口。

你可能会注意到name=&apos;<%= Constants.RES_NEW_FILE_PARAMETER_NAME%>"+i+"&apos;name=&apos;"+i+"&apos;中都有i这个变量,没错,这就是为了能让“附件”和“附件概要”能一一绑定,取到一个“附件”之后,马上根据后缀i就可以取得其相应的“附件概要”。

                       

所以在Action层取作品的相关信息如下:

 

1.             新建一个作品DtoProduct product = new Product();//Product是自己定义的Dto对象。

2.             封装作品基本信息,如:product.setPro_name = ProductForm.getPro_name();

3.             间接取附件信息;

 

有关代码如下:

public ActionForward newProductIn(ActionMapping mapping,

            ActionForm form, 

            HttpServletRequest request,

            HttpServletResponse response){

ProductForm productForm=(ProductForm)form;

//封装作品基本信息

product=new Product ();

product.setPro_name(productForm.getPro_name().trim()); //作品名称

 ……………………  //还有很多其他字段;

 

//开始封装所有的附件和附件概要信息;

Hashtable allfiles= productForm.getMultipartRequestHandler()

.getFileElements();

Hashtable texts=productForm.getMultipartRequestHandler()

.getTextElements(); 

for(int i = 0;i<allfiles.size();i++){ //得到所有附件域的值和其相对应的附件概要的值

String[] fileComnt = (String[])productForm.getMultipartRequestHandler().

getTextElements().get(Integer.toString(i));

FormFilefileCotent = (FormFile)productForm.getMultipartRequestHandler().

getFileElements().get(Constants.RES_NEW_FILE_PARAMETER_NAME+i);

       if(fileCotent.getFileName().equals("")){

                                   continue;

                                                 }

     else{//取附件信息和附件概要信息进行封装
productFileInfor=new ProductFileInfor();(productFileInfor
为自己定义Dto,用来存储附件信息)

       InputStream in=fileCotent.getInputStream();

       productFileInfor.setInput_file_stream(in);//设置输入流                  productFileInfor.setFile_comment(fileComnt[0]);

 

}

                           

以上为本人自己设计的多附件上传方案。

 

第二种方案:直接动态多附件上传

这个方案为借鉴网上已有设计,但原创者的设计在实施上存在一些错误,因此本人把其中设计进行改进,同时实现第一种方案的业务需求。

首先:ActionForm设计

public class MultiUploadForm extends ActionForm {

     /**

      *

      */

     private static final long serialVersionUID = 1L;

     private List myFiles;

    @SuppressWarnings("unchecked")

     public MultiUploadForm(){

        myFiles = new ArrayList();

        //为了能够在页面初始显示一个file

        myFiles.add(new UploadFile());

    }

    public List getMyFiles() {

        return myFiles;

    }   

 

  //注意这个方法的定义,非常重要,实现动态上传完全在于这个函数的定义

 

   @SuppressWarnings("unchecked")

public UploadFile getUploadFile(int index){

        int size = myFiles.size();

       if (index > size-1) {

             for (int i=0;i<index-size+1;i++){

             myFiles.add(new UploadFile());

             }

             }

 

        return (UploadFile)myFiles.get(index);

    }

    public void setMyFiles(List myFiles) {

        this.myFiles = myFiles;

    }

                        

Dto定义:

public class UploadFile implements Serializable {

 

 

    /**

 

 

  

      *

        */

       private static final long serialVersionUID = 1L;

     

  private FormFile file;

     

  String  file_comment;

 

   public String getFile_comment() {

                   

  return file_comment;

     

  }

    

   public void setFile_comment(String file_comment) {

 

 

                     this.file_comment = file_comment;

  

     }

       public FormFile getFile() {

 

 

    

    System.out.println("run in uploadFile.getFile()");

  

 

     return file;

 

    }

 

 

    public void setFile(FormFile file) {

 

        this.file = file;

 

    }

 

}

 

 

Jsp代码:

 

<%@ page language="java" pageEncoding="UTF-8"

  import = "com.icss.multifile.web.form.MultiUploadForm"

%>

 

<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>

<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%>

<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles"%>

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>

<%@ taglib uri="/WEB-INF/struts-nested.tld" prefix="nested"%>

 

<html:html>

<head>

       <title>

              multiUploadDemo

       </title>

       <SCRIPT  language="javascript" charset="">

      

        var num = 0;

function add_Row(the_table)    { //动态增加一行,实际上也就是增加一个表格

             

          var    the_row,the_cell;  

          var    cur_rows=the_table.rows.length;

          the_row=cur_rows==null?-1:(cur_rows);

       //   var    i=the_row;    

          var    newrow=the_table.insertRow(num);//得到插入位置 

                 newrow.id =num;       ;

         <%   MultiUploadForm multiUploadForm=(MultiUploadForm)request.getAttribute("multiUploadForm");

         int  size = 1;

         if(multiUploadForm!=null && multiUploadForm.getMyFiles()!=null && multiUploadForm.getMyFiles().size()>0 ){

         size =  multiUploadForm.getMyFiles().size();

         }

             

          

          

             %>

          the_cell=newrow.insertCell(0);

                        the_cell.innerHTML="<table width=&apos;359&apos; border=&apos;0&apos; cellspacing=&apos;0&apos; id=&apos;table&apos;>" 

                    + "<tr>"

                    + "<td width=&apos;300&apos;><input type=file name=uploadFile[<%= size%>].file value=&apos;&apos;></td>"                  

                    + "</tr>"

                    + "<tr>"

                    + "<td ><span class=&apos;useBB&apos;>文件概要[&lt;=50]</span></td>"

                    + "<td class=&apos;style6&apos;>&nbsp;</td>"

                    + "</tr>"

                    + "<tr>" 

                     + "<td>"

                    + "<textarea  name=uploadFile[<%= size%>].file_comment  class=&apos;new_files_comnt&apos; ></textarea></td>"              

                    + "<td align=&apos;left&apos; valign=&apos;top&apos;>&nbsp;"

                    + "</td>"

                    + "</tr>"

                    + "</table><hr>"; 

        

             num++;               

   }  

 

 

 

 

 

 

 

 

 

  function upload(){

     multiUploadForm.submit();

   }

      

       </SCRIPT>

      

</head>

 

<body bgcolor="#ffffff">

       <html:form method="post" action="/multiUploadAction.do" enctype="multipart/form-data">

              <TABLE id=&apos;mytable&apos;>

              <logic:iterate id="uploadFile" property="myFiles" name="multiUploadForm" indexId="index">

                                   <tr><td>     

                                          <html:file property="file" name="uploadFile" indexed="true" />

                                          <html:textarea property="file_comment" name="uploadFile" indexed="true" ></html:textarea>

                                   </td>

                                          </tr>

                                       

                            </logic:iterate>

                                                                                          

                                                                                                                                                                 </TABLE>

             

              <table border="1">

                     <TBODY>

                            <br>

                            <br>

 

                            this is file

                           

                           

 

 

                            <TR>

                                   <input type="button" name="btnAddFile" value="Add File" onclick="add_Row(mytable)" />

                            <TR>

                                   <TD id="tdTarget"></TD>

                                   <input type="button" name="btnUpload" value="upload" onclick="upload()">

                     </TBODY>

              </table>

       </html:form>

</body>

</html:html>

 

 

Action代码:

public class MultiUploadAction extends Action {

    public ActionForward execute(ActionMapping mapping, ActionForm form,

            HttpServletRequest request,

            HttpServletResponse response) {

MultiUploadForm multiUploadForm = (MultiUploadForm) form;

List myFiles = multiUploadForm.getMyFiles();

for(int i =0;i<myFiles.size();i++){

UploadFile uploadFile = (UploadFile)myFiles.get(i);

FormFile file = uploadFile.getFile();

 

if(file==null){

System.out.println("file is null");

}

else{

 

//能运行到这里,就可以使用单个文件上传的方法进行上传了,做循环;

 

System.out.println("filename========" + file.getFileName());

System.out.println("file size=======" + file.getFileSize());

System.out.println("file Comment=======" + uploadFile.getFile_comment());

}

}  

return mapping.findForward("success");

}  

}

上面两种方法比较起来,第二种方案的代码聚合度占领上风,目前,还是非常欣赏 这个

 

方案,它完全利用了Struts的结构设计优势,因此在验证和取值上都非常方便。因

 

 

 

此,

    在这里特意和大家共享。

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值