零基础学Struts
上QQ阅读APP看书,第一时间看更新

7.4 Struts 2实现上传多个文件

前面介绍的都是上传一个文件,其实Struts 2也可以很方便地实现多文件上传。如果页面中有多个文件域需要实现文件上传,则只需在Action中为每个文件域指定3个属性,分别用来封装上传文件、上传文件类型、上传文件名。

7.4.1 使用数组实现上传多个文件

前面介绍的都是上传单个文件,下面来看如何实现上传多个文件。

在Action中为每个文件域指定3个属性,确实可以实现多个文件的上传,但是这样使得代码过于臃肿,而且失去了灵活性。如果以后要添加一个文件域,那就必须在Action中为其添加相应的属性。

这时可以使用数组或者List来封装所有的文件域,不过前提是这些文本域的name属性必须相同。

(1)新建一个用户输入页,添加两个文件域,其name属性都为myFile,代码如下所示。

        <form action="upload.action" method="post" enctype="multipart/form-data">
          <table>
                <tr>
                      <td>用户名:</td>
                      <td><input type="text" name="username" ></td>
                </tr>
                <tr>
                        <td>上传文件1:</td>
                        <td><input type="file" name="myFile"></td>
                  </tr>
                  <tr>
                        <td>上传文件2:</td>
                        <td><input type="file" name="myFile"></td>
                  </tr>
                  <tr>
                        <td><input type="submit" value="上传"></td>
                        <td><input type="reset"></td>
                  </tr>
            </table>
          </form>

(2)新建业务逻辑控制器Action用来处理多文件上传。因为上面的两个文本域有相同的name属性,这样就可以使用数组类型的属性封装这两个文本域。3个数组类型的属性分别用来封装上传文件、上传文件类型、上传文件名,代码如下所示。

        package net.hncu.struts2.action;
        import java.io.File;
        import java.io.FileInputStream;
        import java.io.FileOutputStream;
        import java.io.InputStream;
        import java.io.OutputStream;
        import org.apache.struts2.ServletActionContext;
        import com.opensymphony.xwork2.ActionSupport;
        public class UploadAction extends ActionSupport {
              // username属性用来封装用户名
              private String username;
              // myFile属性用来封装所有上传的文件
              private File[] myFile;
              // myFileContentType属性用来封装所有上传文件的类型
              private String[] myFileContentType;
              // myFileFileName属性用来封装所有上传文件的文件名
              private String[] myFileFileName;
              private String savePath;
              //获得上传文件保存目录
              public String getSavePath() {
                    return savePath;
              }
              //设置上传文件保存目录
              public void setSavePath(String savePath) {
                    this.savePath = savePath;
              }
              //获得myFile
    public File[] getMyFile() {
          return myFile;
    }
    //设置myFile
    public void setMyFile(File[] myFile) {
          this.myFile = myFile;
    }
    //获得myFileContentType
    public String[] getMyFileContentType() {
          return myFileContentType;
    }
    //设置myFileContentType
    public void setMyFileContentType(String[] myFileContentType) {
          this.myFileContentType = myFileContentType;
    }
    //获得myFileFileName
    public String[] getMyFileFileName() {
          return myFileFileName;
    }
    //设置myFileFileName
    public void setMyFileFileName(String[] myFileFileName) {
          this.myFileFileName = myFileFileName;
    }
    //获得username
    public String getUsername() {
          return username;
    }
    //设置username
    public void setUsername(String username) {
          this.username = username;
    }
    public String execute() throws Exception {
          //取得用来上传的文件数组
          File[] files = getMyFile();
          //循环每个上传的文件
          for (int i = 0; i < files.length; i++) {
                //基于file[i]创建一个文件输入流
                InputStream is = new FileInputStream(files[i]);
                // 设置上传文件目录
                String uploadPath = ServletActionContext.getServletContext()
                          .getRealPath(getSavePath());
                // 设置目标文件
                File toFile = new File(uploadPath, getMyFileFileName()[i]);
                // 输出流
                            OutputStream os = new FileOutputStream(toFile);
                            //设置缓存
                            byte[] buffer = new byte[1024];
                            int length = 0;
                            //读取file[i]文件输出到toFile文件中
                            while ((length = is.read(buffer)) > 0) {
                                  os.write(buffer, 0, length);
                            }
                            //关闭输入流
                            is.close();
                            //关闭输出流
                            os.close();
                      }
                      return SUCCESS;
                }
            }

7.4.2 测试使用数组实现上传多个文件

打开用户输入页,填写用户名并选择文件进行上传,如图7.26所示。

页面跳转到结果输出页。页面中显示了用户名以及上传的文件名,如图7.27所示。

图7.26 用户输入页

图7.27 结果显示页

下面打开文件上传目录upload02,在该目录中可以看到刚才上传的文件,如图7.28所示。

这里要注意的是,通过拦截器配置的文件最大值只是针对一个文件来说。比如,配置的文件大小的最大值为50KB,虽然上传的两个文件大小加起来大于50KB,但是同样可以完成上传。

如果需要配置所有文件和的最大值,可以在“struts.xml”文件中配置struts.multipart.maxSize常量,改变其默认大小,代码如下所示。

        <constant name="struts.multipart.maxSize" value="20721520"></constant>

如果其中有一个上传文件不符合要求,那么所有的文件都不会被上传。页面将跳转回用户输入页,并提示输入错误信息,如图7.29所示。如果有多个文件不符合要求,将输出多条错误信息,如图7.30所示。

图7.28 上传目录upload02

图7.29 输出错误提示信息(1)

7.4.3 使用List实现上传多个文件

图7.30 输出错误提示信息(2)

这里还可以使用List来处理多个文件的上传,这种方式和使用数组基本类似。只需要将使用数组类型封装文件域中的数组类型替换成List类型就可以了,修改代码如下所示。

        package net.hncu.struts2.action;
        import java.io.File;
        import java.io.FileInputStream;
        import java.io.FileOutputStream;
        import java.io.InputStream;
        import java.io.OutputStream;
        import java.util.List;
        import org.apache.struts2.ServletActionContext;
        import com.opensymphony.xwork2.ActionSupport;
        public class UploadAction extends ActionSupport {
              // username属性用来封装用户名
              private String username;
              // myFile属性用来封装所有上传的文件
              private List<File> myFile;
              // myFileContentType属性用来封装所有上传文件的类型
    private List<String> myFileContentType;
    // myFileFileName属性用来封装所有上传文件的文件名
    private List<String> myFileFileName;
    private String savePath;
    //获得上传文件保存目录
    public String getSavePath() {
          return savePath;
    }
    //设置上传文件保存目录
    public void setSavePath(String savePath) {
          this.savePath = savePath;
    }
    //获得myFile
    public List<File> getMyFile() {
          return myFile;
    }
    //设置myFile
    public void setMyFile(List<File> myFile) {
          this.myFile = myFile;
    }
    //获得myFileContentType
    public List<String> getMyFileContentType() {
          return myFileContentType;
    }
    //设置myFileContentType
    public void setMyFileContentType(List<String> myFileContentType) {
          this.myFileContentType = myFileContentType;
    }
    //获得myFileFileName
    public List<String> getMyFileFileName() {
          return myFileFileName;
    }
    //设置myFileFileName
    public void setMyFileFileName(List<String> myFileFileName) {
          this.myFileFileName = myFileFileName;
    }
    //获得username
    public String getUsername() {
          return username;
    }
    //设置username
    public void setUsername(String username) {
          this.username = username;
    }
    public String execute() throws Exception {
                    //取得用来上传的文件数组
                    List<File> files = getMyFile();
                    //循环每个上传的文件
                    for (int i = 0; i < files.size(); i++) {
                            //基于file[i]创建一个文件输入流
                            InputStream is = new FileInputStream(files.get(i));
                            // 设置上传文件目录
                            String uploadPath = ServletActionContext.getServletContext()
                                        .getRealPath(getSavePath());
                            // 设置目标文件
                            File toFile = new File(uploadPath, getMyFileFileName().get(i));
                            // 输出流
                            OutputStream os = new FileOutputStream(toFile);
                            //设置缓存
                            byte[] buffer = new byte[1024];
                            int length = 0;
                            //读取file[i]文件输出到toFile文件中
                            while ((length = is.read(buffer)) > 0) {
                                    os.write(buffer, 0, length);
                            }
                            //关闭输入流
                            is.close();
                            //关闭输出流
                            os.close();
                    }
                    return SUCCESS;
              }
        }