common-fileupload是jakarta项目组开发的一个功能很强大的上传文件组件,可以支持多个文件同时上传,同时也可以除了将上传文件保存为文件之外,还可以将上传的文件数据提取保存至数据库中,甚至你可以通过调用其中提供的API,在程序代码中获得上传文件的内容,这样你就可以处理这些数据了,这个当然与具体的应用有关了。 这里只讲common-fileupload的简单使用入门,一并解决上传文件中文件名为中文时,上传之后文件名显示乱码的问题,这个解决方法很简单,在示例程序代码中的注释中有详细的描述,查看程序就可以明白了。同时这里的示例代码中,只提供了一个文件上传框的显示,但是在后台提供了多个文件上传的读取支持的,只要能够基本明白这个上传方法,做成多个文件上传也不成问题。 另外还需说明的是,对于上传文件,通常前台上传文件至后台时,后台是一个Servlet来处理请求,而Servlet处理请求中,通常会有返回页面,所以如果要做到界面显示,而不会让用户感觉有因为上传而产生的刷屏的样子,应该做一个类似于AJAX的表现,来进行局部刷新,不过AJAX本身而言,并不支持form的post方式的文件提交,所以不能用AJAX来进行上传文件的局部刷新。通常比较好的一种做法是在你的网页中内嵌一个iframe,在iframe里面做一个form,以进行文件上传的提交。具体示例代码见下。 本次的上传使用的Common-FileUpload的版本是最新版,即 好了,不说废话了,下面贴出示例代码: WEB页面: 文件名:uploadtest.html <html> <head> <title>文件上传</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> </head> <body> <p> <b>文件上传</b> </p> <br/> <br/> <div id="fileSendDiv"> <iframe width="100%" height="35" frameborder="0" id="show" name="show" src="uploadfile.jsp" scrolling="no" style="frameborder:0" align="left"></iframe> </div> <br/> <br/> <br/> <br/> <p> <b>刷新的是iframe,父页面不会改变</b> </p> </body> </html> 该页面注意的是iframe的使用,刷新的会是iframe,iframe指向了一个新的文件,文件名叫:uploadfile.jsp,这个才是真正的上传文件的内容表现,你可以将这个文件作为工具类型的文件,只要在上传文件中通过iframe引用这个文件即可(uploadtest.html与uploadfile.jsp处于同一个目录中)。 上传显示文件代码如下: 文件名:uploadfile.jsp <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W <html> <head> <title>上传文件</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <script language="JavaScript" type="text/javascript"> function upload() { var filename = document.tab.uploadfile.value; if (filename=='') { alert("没有选择要上传的文件,请选择!"); return; } document.tab.action = "FileUpload";//提交上传为文件时,所指向的servlet配置的Servlet动作 document.tab.target="show";//指向iframe的ID,即刷新页面返回时所指的地方。 document.tab.submit(); } </script> </head> <body style="margin:0px;"> <form name="tab" method="post" action="" enctype="multipart/form-data"> <input type="file" id="uploadfile" name="uploadfile" style="border:1px solid black;" > <input type="button" name="up" value="上传" style="border:1px solid black;height:20px;" onClick="upload()"> </form> </body> </html> 需要明确的是该上传文件当调用upload之后,其返回所指向的是ID为show表单,查看uploadtest.html中的iframe发现,指的就是这个iframe的ID,所以说当后台的Servlet有返回时,刷新的也只是这个iframe,而不会影响整个父页面的显示效果。 下面是后台Servlet的源代码: 文件名:UploadFileTest.java package com.uploadtest; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.Iterator; import java.util.List; 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.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; public class UploadFileTest extends HttpServlet { private static final long serialVersionUID = private static final String CONTENT_TYPE = "text/html; charset=utf-8"; //Process the HTTP Post request public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String path = request.getContextPath(); //WEB形式的表现地址,示例:http://127.0.0.1:8080/uploadtest/ String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; //获得本地地址,示例如:c://tomcat/webapp/ String temp = getServletContext().getRealPath("/") + "upload/temp"; //临时目录 String loadpath = getServletContext().getRealPath("/") + "upload"; //上传文件存放目录 response.setContentType(CONTENT_TYPE); PrintWriter out = response.getWriter(); try { //Create a factory for disk-based file items DiskFileItemFactory factory = new DiskFileItemFactory(); //Set factory constraints设置最多只允许在内存中存储的数据,单位:字节 factory.setSizeThreshold(4096); //设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录(缓存) factory.setRepository(new File(temp)); //Create a new file upload handler ServletFileUpload upload = new ServletFileUpload(factory); // Set overall request size constraint设置允许用户上传文件大小,单位:字节,这里设为 upload.setSizeMax(5 * 1024 * 1024); //Parse the request List /* FileItem */fileItems = upload.parseRequest(request); //开始读取上传信息 // 依次处理每个上传的文件 Iterator iter = fileItems.iterator(); while (iter.hasNext()) { FileItem item = (FileItem) iter.next(); //忽略其他不是文件域的所有表单信息 if (!item.isFormField()) { String name = item.getName(); long size = item.getSize(); if ((name == null || name.equals("")) && size == 0) continue; name = name.substring(name.lastIndexOf("\\") + 1);//从全路径中提取文件名 //处理中文编码问题,前台是UTF-8,所以这里需要对应上,如果前台是gb2312的话,这里也应该是gb2312 name = new String(name.getBytes(), "utf-8"); try { //保存上传的文件到指定的目录 //在下文中上传文件至数据库时,将对这里改写 File fNew = new File(loadpath, name); item.write(fNew); //out.print(name + " " + size + ""); response.sendRedirect(basePath + "uploadfile.jsp");//返回刷新页面,即返回iframe } catch (Exception e) { e.printStackTrace(); out.println(e); } } } } catch (Exception e) { e.printStackTrace(); } } } 具体的调用说明,见源文件中的注释 最后就剩下web.xml的配置了,下面是示例: <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java./xml/ns/j2ee" xmlns:xsi="http://www./2001/XMLSchema-instance" xsi:schemaLocation="http://java./xml/ns/j2ee http://java./xml/ns/j2ee/web-app_2_4.xsd"> <display-name>UploadFile</display-name> <servlet> <description></description> <display-name>FileUpload</display-name> <servlet-name>FileUpload</servlet-name> <servlet-class> com.uploadtest.UploadFileTest </servlet-class> </servlet> <servlet-mapping> <servlet-name>FileUpload</servlet-name> <url-pattern>/FileUpload</url-pattern> </servlet-mapping> </web-app> 好了,一个完整的使用Common-FileUpload的例子就结束了。 最后要提一点,就是这个上传组件中,在解析上传文件时,会读取上传文件的内容的,有时在应用中,比如WEB呼叫中心方面,WEB端上传的文件会被远端的人员接收,但是有时的情况下,远端服务人员并不一定希望接收WEB端发过来的文件,所以即便是远端服务人员拒绝了接收文件,但是这个上传组件却是已经读取了文件的内容至缓存中了,也就是说多做了一步。并且即便是远端服务人员愿意接收文件,它也是有延迟的,过程是先从WEB中接收文件至缓存中,再从缓存中提取数据传至远端的服务人员。估计可以通过改变这个上传组件的源代码,来回避上面所说的问题,不过需要对源代码有一定的研究。 至于用到该上传组件的一些高级功能(如要做一个上传进度条的显示),可以看它提供的User Guide,进行自身功能的定义了,本文只做入门级介绍。 |
|
来自: Blex > 《Jsp&Java》