Struts2上传文件及相关总结

Struts2本身没有提供解析上传文件内容的功能,它通过第三方上传组件来实现文件上传的功能。So,我们通过使用Struts2实现文件上传的功能,首先要将commons-fileupload-1.2.1.jar和commons-io-1.4.jar复制到项目的WEB-INF/lib目录下。

Struts2的上传组件只有一个拦截器: org.apache.struts2.interceptor.FileUploadInterc eptor(这个拦截器不用配置,是自动装载的),它负责调用底层的文件上传组件解析文件内容,并为Action准备与上传文件相关的属性值。

下面是上传单个文件JSP页面代码片段,上传页面的表单中有file和text两种类型的元素。
singleupload.jsp:

 <!--在进行文件上传时,表单提交方式一定要是post的方式,因为文件上传时二进制文件可能会很大,还有就是enctype属性,这个属性一定要写成multipart/form-data,不然就会以二进制文本上传到服务器端--> 

<th>日期</th>
<td>
  <input type="text" id="startdate" name="startdate" />
</td>
<th>文件上传&nbsp;</th>
<td colspan="3">
  <input type="file" id="upload" name="upload" size="45" >
</td>

以下是对应的请求action,一般文件上传后会先生成一个.tmp临时文件:
方法1:
通过临时文件获取数据。

这里要强调的是:处理文件上传请求的Action必须提供特殊样式命名的属性。例如,假设表单中文件选择框的名字为upload,那么Action就应该提供以下三个属性upload,uploadFileName,uploadContentType来分别表示上传文件的File对象、上传文件名以及上传文件内容类型

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import jxl.Sheet;
import jxl.Workbook;
import lombok.Data;

public @Data class UploadAction extends BaseAction {
// @Data映射getter,setter 方法
    private File upload;  //file表单
    private String startdate;
    private String uploadFileName;//提交过来的file的名字
    private String uploadContentType;//提交过来的file的MIME类型

    public void uploadReport() {
        try {
            String str="";
            InputStream is = new FileInputStream(upload);
            Workbook rwb = Workbook.getWorkbook(is);
            int sheetCount = rwb.getNumberOfSheets();
            Sheet rs = rwb.getSheet(0);
            int rows = rs.getRows(); // 行
            int cols = rs.getColumns(); // 列
            for (int i = 0; i < rows ; i++) {
                str=rs.getCell(0,i).getContents().trim();
            }

        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }

}

这里的upload并不是真正指代jsp传过来的文件,而是一个临时文件。当文件上传过来时,struts2首先会寻找struts.multipart.saveDir所指定的存放位置(我们也可以新建一个struts.properties属性文件来指定临时文件的位置),如果没有指定,那么文件会存放在tomcat的work\Catalina\localhost\目录下
debug upload

这种方法能获取到upload临时文件,也能够获取到表单元素内的值。如果要获取真正的文件,我们可以制定文件上传后的存放位置,然后通过输出流将其写到流里面就行了,如以下代码段

//此代码段暂时没写 

方法2:
也可以通过以下的这个方法来获取上传文件


import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import jxl.Sheet;
import jxl.Workbook;
import lombok.Data;

public @Data class UploadAction extends BaseAction {

    public void uploadReport() {
        String str="";
        int rows = 0;
        List<FileItem> templist = null;
        // 上传文件这开始
        try {
            String contentType = this.getRequest().getContentType(); // 获取客户端给服务器发送数据的格式

            File filedir = new File(System.getProperty("user.dir") + "/1fileTop");
            HttpServletRequest request = this.getRequest();
            DiskFileItemFactory difactory = new DiskFileItemFactory(); // 对象的工厂,可以设定缓冲区大小和存放临时文件目录。
            difactory.setSizeThreshold(1024 * 1024 * 3); // 设定的缓冲区 3M,如果不指定,那么缓冲区的大小默认是10KB
            difactory.setRepository(filedir); // 设置上传文件的临时目录

            ServletFileUpload sfu = new ServletFileUpload(difactory);
            sfu.setHeaderEncoding("UTF-8");// 解决上传文件名的中文乱码

            templist = (List<FileItem>) sfu.parseRequest(request); // 解析request请求
            System.out.println("templist:" + templist.size());
            Map param = new HashMap();
            if (templist != null && templist.size() > 0) {
                // 遍历判断是表单输入域 还是 文本上传域
                for (FileItem item : templist) {
                    if (item.isFormField()) {
                        param.put(item.getFieldName(), item.getString("UTF-8"));// 如果你页面编码是utf-8的
                        System.out.println("普通输入项");
                    } else {
                        System.out.println("上传文件输入项");
                        Workbook rwb = Workbook.getWorkbook(item.getInputStream()); //获取文件的输入流
                        int sheetCount = rwb.getNumberOfSheets();
                        Sheet rs = rwb.getSheet(0);
                        rows = rs.getRows(); // 行
                        int cols = rs.getColumns(); // 列
                        for (int i = 0; i < rows; i++) {
                            str=rs.getCell(0, i).getContents().trim(); // getCell(列,行)
                        }
                    }
                }

            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // 获取文件结束
    }

通过这种方法进行文件上传可能会遇到的异常:
1.无法通过属性的getter,setter方法来获取表单中对应的属性值,可以通过以上方法中item.getString(“UTF-8”)单个获取,但是比较麻烦,特别是对于表单是一个封装的对象来说
2.解析request请求时,debug得到request里有值,但是sfu.parseRequest(request)解析request为空。原因大概是struts2的源代码FileUploadInterceptor在跳转到action对应的方法之前已经对request进行了解析,而request只能被解析一次。
这个问题需要根据struts2-core-2.3.15.2.jar的包名来解决。
a.如果struts2是status2.3.4 , 在配置文件struts.xml里加上

<bean type= "org.apache.struts2.dispatcher.multipart.MultiPartRequest" name= "myRequestParser" class= "com.icf.common.base.actions.RequestParseWrapper" scope= "default" optional= "true " /> 
<constant name= "struts.multipart.handler" value= "myRequestParser" />

public class RequestParseWrapper  extends JakartaMultiPartRequest   {
    public void parse(HttpServletRequest servletRequest, String saveDir)throws IOException{  

 }   
}

b.如果struts2是struts2.3.15.1以后的版本,在struts2.3.15.1后的配置里,struts2的struts-default.xml 里把 struts.multipart.handler 改成了struts.multipart.parser,在struts配置文件中加上

<bean type= "org.apache.struts2.dispatcher.multipart.MultiPartRequest" name= "myRequestParser" class= "com.icf.common.base.actions.RequestParseWrapper" scope= "default" optional= "true "   /> 
<constant name= "struts.multipart.parser" value= "myRequestParser"   />

创建一个自己的类RequestParseWrapper

import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest;

public class RequestParseWrapper extends JakartaMultiPartRequest {
    @Override
    public void parse(HttpServletRequest arg0, String arg1) throws IOException {

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值