代码改变世界

input上传文件时的注意事项

2013-09-10 12:56  阿昌wining  阅读(711)  评论(0)    收藏  举报

     近几天公司要求开发一个文件上传并入库的功能,功能不难实现,网上代码随处可见!由于要求文件格式为Excel文档,故只能通过file控件上传文件,  并通过ServletFileUpload对象进行解析上传的文件信息,进而获取Excel中的数据信息,具体实现如下:  jsp页面:  <form action="ImportExcelServlet" method="post" enctype="multipart/form-data">   <input type="file" />   <input type="submit" value="导入" />  </form> java代码: 1、servlet实现 import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern;

import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**  * Servlet implementation class ImportExcelServlet  */ public class ImportExcelServlet extends HttpServlet {  private static final long serialVersionUID = 1L;

 // 缓冲区域  File tempPathFile;  // 默认路径  String uploadTo = "D:\\";  // 支持的文件类型  String[] errorType = { ".xls" };  // 格式化日期  SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS");

 /**   * @see HttpServlet#HttpServlet()   */  public ImportExcelServlet() {   super();   // TODO Auto-generated constructor stub  }

 /**   * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse   *      response)   */  protected void doGet(HttpServletRequest request,    HttpServletResponse response) throws ServletException, IOException {   doPost(request, response);  }

 /**   * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse   *      response)   */  protected void doPost(HttpServletRequest request,    HttpServletResponse response) throws ServletException, IOException {   request.setCharacterEncoding("utf-8");   response.setCharacterEncoding("utf-8");   // 取得服务器真实路径   // uploadTo = req.getSession().getServletContext().getRealPath("\\")   // +"upload\\";   // Create a factory for disk-based file items   DiskFileItemFactory factory = new DiskFileItemFactory();   // 设置缓冲区大小,这里是4kb   //factory.setSizeThreshold(4096);   // 设置缓冲区目录   //factory.setRepository(tempPathFile);   // Create a new file upload handler   ServletFileUpload upload = new ServletFileUpload(factory);   // Set overall request size constraint   // 设置最大文件尺寸,这里是4MB   upload.setSizeMax(4 * 1024 * 1024);   // 开始读取上传信息   List fileItems = new ArrayList();   try {    fileItems = upload.parseRequest(request);   } catch (FileUploadException e1) {    e1.printStackTrace();   }   // 依次处理每个上传的文件   Iterator iter = fileItems.iterator();   System.out.println("fileItems的大小是" + fileItems.size());   // 正则匹配,过滤路径取文件名   String regExp = ".+\\\\(.+)$";   Pattern p = Pattern.compile(regExp);   while (iter.hasNext()) {    FileItem item = (FileItem) iter.next();    // 忽略其他不是文件域的所有表单信息    System.out.println("正在处理" + item.getFieldName());    if (!item.isFormField()) {     String name = item.getName();     long size = item.getSize();     if ((name == null || name.equals("")) && size == 0)      continue;     Matcher m = p.matcher(name);     boolean result = m.find();     if (result) {      boolean flag = false;      for (int temp = 0; temp < errorType.length; temp++) {       if (m.group(1).endsWith(errorType[temp])) {        flag = true;       }      }      if (!flag) {       System.out.println("上传了不支持的文件类型");       throw new IOException(name + ": wrong type");      }      try {       String fileName = uploadTo + format.format(new Date())         + m.group(1).substring(m.group(1).indexOf("."));       item.write(new File(fileName));       // 调用ReadExcel类进行读出excel       // ReadExcel.readExcel(fileName, response.getWriter());       System.out.println(name + "\t\t" + size);      } catch (Exception e) {       e.printStackTrace();      }     }    } else {     // 这里添加对不是上传文件表单项的处理     System.out.println("这是一个表单项");    }   }

 }

2、controller实现(dorado项目中) import java.util.ArrayList; import java.util.List; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream;

import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;

import jxl.Sheet; import jxl.Workbook; import jxl.read.biff.BiffException; import jxl.read.biff.File; import jxl.Cell;

import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.log4j.Logger; import com.bstek.dorado.action.Action; import com.bstek.dorado.action.Controller; import com.bstek.dorado.action.mapping.ActionForward;

/**  * 投保单信息导入控制器  * @author yueweinan  *  */ public class PolicyInfoImportController extends Controller {    private Logger logger = Logger.getLogger("PolicyInfoImportController");    /**   * 允许上传文件的扩展名   */  private static String[] fileNameExtension = { ".xls" };  /**   * 允许整个request的大小,默认为1MB   */  private static long sizeMax = 1024 * 1024 * 1024;  /**   * 允许单个文件的最大上传大小,默认为1MB   */  private static long fileSizeMax = 1024 * 1024 * 1024;      @SuppressWarnings("unchecked")  public void doUpload(Action action,    HttpServletRequest request, HttpServletResponse response)    throws Exception {   request.setCharacterEncoding("utf-8");   /*BufferedReader read =  request.getReader();     String line = read.readLine();   while (line != null) {    System.out.println(line);    line = read.readLine();       }*/   /*InputStream inputStream = request.getInputStream();   Workbook workBook = Workbook.getWorkbook(inputStream);*/      if (ServletFileUpload.isMultipartContent(request)) {          try  {      validateSize(request.getContentLength()); //     InputStream stream = request.getInputStream(); //     //     Workbook wookBook = Workbook.getWorkbook(stream);                ServletFileUpload fileupload = new ServletFileUpload(        new DiskFileItemFactory());      fileupload.setSizeMax(sizeMax);      fileupload.setFileSizeMax(fileSizeMax);      fileupload.setHeaderEncoding("UTF-8");      List<FileItem> list =  fileupload.parseRequest(request);      //List<PolicyExecelVo> parseResult = new ArrayList<PolicyExecelVo>();             //1.解析execel      if (list != null) {       //lis的size为1       for (int i=0; i<list.size(); i++) {         FileItem item = list.get(i);         InputStream sm = item.getInputStream();         //         //parseResult = new PolicyParser().ParseExecel(sm);       }      }      //2.装入缓存      String batchNo = "";      /*if (parseResult!= null && parseResult.size()>0) {       batchNo = BatchNoGenerater.generatNo();       PolicyImportCache.push(batchNo, parseResult);      }*/      //3.返回对应的导入批次号到页面      request.setAttribute("isUploadSucc", "true");     // request.setAttribute("batchNO", batchNo);    } catch (Exception e) {     request.setAttribute("isUploadSucc", "false");     throw new Exception(e.getMessage());    }        //return action.findForward("success");       }   request.setAttribute("isUploadSucc", "true");    request.setAttribute("batchNO", "wangchangli");   //return null;  }    private void validateFileName(String fileName) {   for (String allow : fileNameExtension) {    if (!fileName.endsWith(allow)) {     /*throw new BusinessException("“"       + fileName.substring(fileName.lastIndexOf("\\") + 1)       + "”为不允许上传的文件类型!");*/    }   }  }

 private void validateSize(long size) {   if (size > sizeMax) {    /*throw new BusinessException("文件大小超过上限[" + sizeMax / 1024 / 1024      + "MB]");*/   }  } }    

     当前本人使用的vmware虚拟机桌面进行开发的,eclipse开发环境,tomcat 6.0

简单吧;但是看似简单的功能确出现了很奇怪的问题,无论是方法1,还是方法2在List<FileItem> list =  fileupload.parseRequest(request); 的时候,list的size确始终为0;去网上查也没有确切的解决方案。问同事,请教高手都感觉很奇怪;不确信的少年可以把代码拷贝过去试一把;

    查找原因:    

起初,总是以为List<FileItem> list =  fileupload.parseRequest(request);获取FileItem时的代码出现问题,经过查看源代码,并多次debug 发现,解析request的代码没有问题,而是request中没有存在相应的item信息,然后就转向配置文件和jsp页面进行测试;     后来经过反复测试,并加上技术老大帮助下;终于找到原因:原来在解析request对象的时候,input控件必须定义name属性,只有存在name属性的 input控件才能通过fileupload.parseRequest()方法获取对应的FileItem对象信息;尼玛,真奇葩,费了九牛二虎之力终于解决了此问题。希望以后 对大家有所帮助;

     另外,本人对request的页面提交机制不是很了解,如果哪位大侠能够给出相关的解释。将感激万分!!!!!!!!!!!!!!