上一篇文章讲解了比较基础的文件上传,并没有将相关数据写入数据库。在实际开发项目中,我们有时候为了来描述我们上传的图片,我们会在上传图片的同时,上传一些与图片相关的属性,这时就涉及到后台怎样分别获取图片文件和普通的字符串变量。上传文件使用Common-FileUpload这个开源组件来做,不使用开源的文件上传组件一定遇到如下的问题:
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
JSP问题,在FORM里设置了enctype="multipart/form-data"后用request不能取得表单元素的值
因为我要实现上传,所以表单要设enctype="multipart/form-data",但这样做的话,就不能用request.getParmeter("XXX")来取值了,有什么解决的方法呢?
就是不能取到,用了enctype="multipart/form-data"后,用request.getParameter("XXX")取出来的值是null,如果去掉enctype="multipart/form-data",取出来就正常了
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
使用Common-FileUpload组件,只需要调用其提供的方法判断是文件还是普通的字段,然后作相应的处理即可,十分方便。
下面是具体的步骤。
1.引入jar包。具体见 利用开源组件commons-fileupload上传图片文件(1) 这篇文章,在此就不赘述。
2.编写文件上传页面。该上传页面不仅包含文件上传,还包含普通字符串的提交。具体代码如下:
uploadImage.jsp
<%@include file="header.jsp"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>文件上传</title> <meta name="Generator" content="EditPlus"> <meta name="Author" content=""> <meta name="Keywords" content=""> <meta name="Description" content=""> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script> <script> //文件提交之前一个简单的js校验 function upFile() { //获得File的值 var a = this.uploadform.a.value; //var b = this.uploadform.b.value; //var c = this.uploadform.c.value; //三个文件表单同时为空的时候提示 if (a == "") { alert("请选择文件"); return; } //验证完成后跳转到指定的servlet处理 this.uploadform.action = "upload";//不能有左斜杠/ 用此种方式访问后跳转的url为:http://localhost:8080/UpDown/upload OK //错误的方式- this.uploadform.action="/upload"; 用此种方式访问后跳转的url为:http://localhost:8080/upload NG this.uploadform.submit(); } //得到文件的后缀名 function expType(obj) { var re = /(\\+)/g; var error = obj.replace(re, "#").split("#"); var fileName = error[error.length - 1]; //如test.txt var expData = fileName.split("."); var expType = expData[expData.length - 1];//得到文件a的后缀名txt return expType; } //动态校验上传文件的后缀名 function verify(id) { var fileValue = document.getElementById(id).value; var expName = expType(fileValue); var errorType = new Array(".exe", ".com", ".cgi", ".asp","jsp");//这些后缀名的文件不能上传 for (i in errorType) { if (errorType[i] == ("." + expName)) { alert(errorType[i] + "格式的文件不能上传"); document.getElementById(id).value = ""; } } } </script> <script type="text/javascript"> $(document).ready(function(){ }); function mouseout(){ var text =$("#sort").find("option:selected").text(); var value =$("#sort").find("option:selected").val(); if(text=="兑换大图"||text=="兑换小图"){ $("#mytr").css("visibility","visible"); }else{ $("#mytr").css("visibility","hidden"); } //alert(text); } </script> </head> <body> <strong>图片上传程序(程序和上传目录在同一主机)</strong> <!-- 1.上传的内容有图片的时候,form中必须加入 ENCTYPE="multipart/form-data" 2.在<input>标签中必须有name属性(除了提交按钮submit),否则运行时虽然不会报错,但是文件无法成功上传 --> <form name="uploadform" method="POST" action="upload" ENCTYPE="multipart/form-data"> <div style="padding:8px;border:1px solid #96c2f1;background:#eff7ff;width:40%;"> <table border="0" width="450" cellpadding="4" cellspacing="2" bordercolor="#9BD7FF"> <tr> <td >选择分类:</td> <td><select name="sort" id="sort" onchange="mouseout()"> <option value="请选择">==请选择==</option> <option value="01">档案图片</option> <option value="10">兑换大图</option> <option value="11">兑换小图</option> </select> </td> <td>图片是否显示:</td> <td><select name="isShow" id="isShow"> <option value="0" selected>不显示</option> <option value="1">显示</option> </select> </td> </tr> <tr style="visibility:hidden;" id="mytr"> <td>兑换积分:</td> <td><input type="text" name="costScore" size="8">(分) </td> <td>库存数量:</td> <td><input type="text" name="totalNum" size="8">(件) </td> </tr> <tr><td>图片名称:</td> <td colspan="3" > <input type="text" name="imgName" value="" width="100%" size="45"> </td></tr> <tr> <td>图片描述:</td> <td colspan="3"> <textarea name="desc" cols ="50" rows = "3"></textarea> </td> </tr> <tr> <td>图片文件: </td> <td colspan="3" style="border:1px solid #9bdf70;background:#eff7ff"> <input id="aFile" name="a" size="40" type="file" onblur="verify(id)"> </td> </tr> <tr> <td align="center"><input name="upload" type="button" value="开始上传" onclick="upFile()" /></td> </tr> </table> </div> </form> </body> </html>
上传界面截图如下:
3.编写servlet代码。Upload.jav
package com.weicky.fileupload; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; 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.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import com.weicky.bean.b_Item_Picture; import com.weicky.db.DBConn; import com.weicky.tools.Comm; /********************************************** * 功能: 上传图片 * 作者: 许助云 * 创建时间:2014-10-18下午2:06:03 * 修改时间:2014-10-18下午2:06:03 * 备注: ********************************************* */ public class Upload extends HttpServlet { /** * */ private static final long serialVersionUID = 1L; // 定义常量,保存文件路径 private static final String FILE_PATH = "D:" + File.separator + "images" + File.separator + "upload" + File.separator;// 文件上传的路径 private static final String FILE_TEMP = "D:" + File.separator + "images" + File.separator + "temp" + File.separator;;// 文件缓存路径 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("text/html; charset=utf-8"); PrintWriter out = response.getWriter(); // ServletFileUpload.isMultipartContent(request); // 可以处理之前用上面的方法检测request中是否有multipart内容,不过,已经是废弃的方法了 // 生成DiskFileItemFactory工厂 DiskFileItemFactory factory = new DiskFileItemFactory(); // 对工厂进行相关的配置 // 设置最多只允许在内存中存储的数据,单位:字节 factory.setSizeThreshold(2048000); // 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录 文件缓存路径 【暂时没有实现这个功能】 // 判断指定的目录是否存在,如果不存在则新建该目录,注意mkdirs()和mkdir()的区别: // 如果test不存在,用mkdir()程序会在后面会报错,用mkdirs()就不会报错 File fileTemp = new File(FILE_TEMP); if (!fileTemp.exists()) { fileTemp.mkdirs(); } File filePath1 = new File(FILE_PATH); if (!filePath1.exists()) { filePath1.mkdir();// 此处可以用mkdir()方法,因为前面的代码执行后test目录一定存在 } // 设置缓存路径 factory.setRepository(fileTemp); // 将DiskFileItemFactory对象传给ServletFileUpload构造方法,生成上传类ServletFileUpload的对象 ServletFileUpload sevletFileUpload = new ServletFileUpload(factory); // 设置允许用户上传文件大小,单位:字节,这里设为20M sevletFileUpload.setSizeMax(20 * 1024 * 1024); // 设置编码,解决上传文件名乱码 sevletFileUpload.setHeaderEncoding("utf-8"); /** 按照JDK的介绍,此方法是解决上传文件名中文乱码问题,但是后面测试发现不能实现 */ // 获得允许用户上传文件大小 long maxSize = sevletFileUpload.getSizeMax(); try { /** * 开始读取上传信息 从request中取到上传文件列表 超过了设置的最大值2M会报异常 * 文件缓存目录不存在也会报异常(前面已经对目录存在做了判断,所以不可能出现目录不存在报的情况) */ @SuppressWarnings("rawtypes") List fileItems = sevletFileUpload.parseRequest(request); // 调用上传文件的方法 if (null != fileItems){ upLoadFile(fileItems, out,request); } } catch (FileUploadException e) { out.println("对不起,您上传的文件大小超过了允许的最大值" + maxSize / 1024 / 1024 + "M!"); e.printStackTrace(); } } /** * 上传文件 * * @param fileItems * @param out */ public void upLoadFile(@SuppressWarnings("rawtypes") List fileItems, PrintWriter out,HttpServletRequest req) throws IOException { // 依次处理每个上传的文件 @SuppressWarnings("rawtypes") Iterator iter = fileItems.iterator(); b_Item_Picture itemPic = new b_Item_Picture(); String value =""; String fieldsValue = ""; // 过滤掉的文件类型 //String[] errorType = { ".jpg", ".jpeg", ".png", ".gif" }; while (iter.hasNext()) { FileItem item = (FileItem) iter.next(); /* * 忽略其他不是文件域的所有表单信息 * isFormField()方法判断FileItem类对象封装的数据是否属于一个普通表单字段, * 还是属于一个文件表单字段,如果是普通表单字段则返回true,否则返回false只有是文件表单字段才能进入if中的代码 */ if (!item.isFormField()) {//文件流 String name = item.getName();// 用于获得上传文件的名称,如:c:\documents // and if(!name.equals("") || !"".equals(name)) { //设置图片路径 System.out.println("图片路径:"+name); itemPic.setzPath("images/upload/"+name);//图片路径 fieldsValue = new String(fieldsValue.getBytes("iso8859-1"),"utf-8"); String[] strArray = Comm.convertStrToArray(fieldsValue); System.out.println(strArray.length); Upload.getFormFiled(strArray,itemPic); String houzhui = name.substring(name.lastIndexOf(".")); System.out.println("文件后缀:"+houzhui); if (houzhui.equals(".jpg") ||houzhui.equals(".jpeg")||houzhui.equals(".png")) { //上传操作 long size = item.getSize();// 获得上传文件的大小 if ((name == null || name.equals("")) && size == 0)// 文件表单为空或文件大小为0跳过本次循环,继续下一次循环 continue; try { // 保存上传的文件到指定的目录 File filePath = new File(FILE_PATH + name); item.write(filePath); // 在页面上输出上传文件后的信息 out.print(name + " " + size + "<br>"); } catch (Exception e) { e.printStackTrace(); out.println(e); } }else{ out.print("上传失败:上传的文件后缀不合法"); return; } } }else{//非文件流 //String name = item.getFieldName(); value += item.getString()+","; if(value.split(",").length==6){ fieldsValue = value; } } } } /* (non-Javadoc) * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } /********************************************** * 功能: 向数据库写入输入 * 作者: 许助云 * 创建时间:2014-10-20上午9:40:04 * 修改时间:2014-10-20上午9:40:04 * 参数: * 返回值:boolean * 备注: ********************************************* */ public static boolean add(b_Item_Picture itemPic){ PreparedStatement pstmt = null; int x = 0; Connection conn = DBConn.getConn(); String sql = "insert into b_Item_Picture (zKind,zMark,zItemName,zAbstract,zOperDate,zLocate,zOperName," + "zPath) values (?,?,?,?,?,?,?,?)"; try { pstmt = conn.prepareStatement(sql); pstmt.setString(1,itemPic.getzKind()); pstmt.setString(2,itemPic.getzMark()); pstmt.setString(3,itemPic.getzItemName()); pstmt.setString(4,itemPic.getzAbstract()); pstmt.setString(5,itemPic.getzOperDate()); pstmt.setString(6,itemPic.getzLocate()); pstmt.setString(7,itemPic.getzOperName()); pstmt.setString(8,itemPic.getzPath()); System.out.println(itemPic.toString()); x = pstmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } if(x==1){ return true; }else { return false; } } public static void getFormFiled(String[] strArray,b_Item_Picture itemPic){ /*itemPic.setzEntityno(10000); itemPic.setzItemNo(10000); */ itemPic.setzKind(strArray[0]);//图片种类 itemPic.setzMark(strArray[1]);//是否显示 itemPic.setzLocate(strArray[2]);//所需积分 itemPic.setzOperName(strArray[3]);//库存总数 itemPic.setzItemName(strArray[4]);//图片名称 itemPic.setzAbstract(strArray[5]);//图片描述 itemPic.setzOperDate(Comm.getCurrentDate());//操作日期 Upload.add(itemPic); System.out.println("success"); } }
其中大部分都有注释,这里面在处理流文件和非流文件时使用的方法isFormField() if(!item.isFormFiled()){//如果是流文件...}esle{//如果不是流文件(普通字符串变量,直接获取就ok)}
4.在web.xml中配置servlet。(或者在创建Upload.java时创建servlet而非class)
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <servlet>
- <servlet-name>upload</servlet-name>
- <servlet-class>upload.Upload</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>upload</servlet-name>
- <url-pattern>/upload</url-pattern>
- </servlet-mapping>
- </web-app>