JSP教程(九)—— 文件上传
使用工具:SmartUpload组件,该包已在https://pan.baidu.com/s/1qZcymBE中。
1 上传单个文件
要想进行上传,则必须使用HTML中提供的file控件,而且<form>也必须使用enctype进行封装。
【注】使用enctype封装:表示表单将按照二进制的方式提交,即所有操作表单此时不再是分别提交,而是将所有内容都按照二进制的方式提交。
实例1
上传表单(demo1_1.html)
1 <html> 2 <head> 3 <title>上传单个文件</title> 4 </head> 5 <body> 6 <form action="demo1_2.jsp" method="post" enctype="multipart/form-data"> 7 请选择文件:<input type="file" name="pic"> 8 <input type="submit" value="上传"> 9 </form> 10 </body> 11 </html>
接收图片并保存(demo1_2.jsp)
1 <%@ page contentType="text/html" pageEncoding="GBK" %> 2 <%@ page import="org.lxh.smart.*" %> 3 <html> 4 <head> 5 <title>上传单个文件</title> 6 </head> 7 <body> 8 <% 9 SmartUpload smart = new SmartUpload();//实例化SmartUpload上传组件 10 smart.initialize(pageContext);//初始化上传操作 11 smart.upload();//上传准备 12 smart.save("upload");//将上传文件保存在upload文件夹中 13 %> 14 </body> 15 </html>
在使用SmartUpload时必须严格按照如上程序进行,而最后在保存时只是写了一个upload,表示上传文件的保存文件夹,此文件夹要在根目录中手工建立。
通过demo1_1.html选择的文件,提交到demo1_2.jsp时将会自动保存,而且保持的文件名称与上传的文件名称一样,所以当上传了同样名称的图片时将会出现覆盖的情况。
2 混合表单
如果要上传文件,则表单必须封装,但是当一个表单使用了enctype封装后,其他的非表单控件的内容就无法通过request内置对象取得,此时必须通过SmartUpload类中提供的getRequest()方法取得全部的请求参数。
实例2
上传表单(demo2_1.html)
1 <html> 2 <head> 3 <title>混合表单</title> 4 </head> 5 <body> 6 <form action="demo2_2.jsp" method="post" enctype="multipart/form-data"> 7 姓名:<input type="text" name="uname"><br> 8 照片:<input type="file" name="pic"><br> 9 <input type="submit" value="上传"> 10 <input type="reset" value="重置"> 11 </form> 12 </body> 13 </html>
接收表单文本、图片并保存(demo2_2.jsp)
1 <%@ page contentType="text/html" pageEncoding="GBK"%> 2 <%@ page import="org.lxh.smart.*"%> 3 <html> 4 <head> 5 <title>混合表单</title> 6 </head> 7 <body> 8 <% 9 request.setCharacterEncoding("GBK") ; 10 %> 11 <% 12 SmartUpload smart = new SmartUpload();//实例化SmartUpload上传组件 13 smart.initialize(pageContext);//初始化上传操作 14 smart.upload();//上传准备 15 String name = smart.getRequest().getParameter("uname");//接受请求参数 16 smart.save("upload");//将上传文件保存在upload文件夹中 17 %> 18 <%=smart.getFiles().getFile(0).getFileName().matches("^\\w+.(jpg|gif)$")%> 19 <h2>姓名:<%=name%></h2> 20 <img src="../upload/<%=fileName%>"> 21 </body> 22 </html>
由于表单进行了二进制封装,所以单纯靠request对象是无法取得提交参数的,必须依靠SmartUpload类中的getRequest().getParameter()方法才能取得请求的参数。
3 为上传文件自动命名
在上传操作中,如果多个用户上传的文件名称一样,则肯定会发生覆盖的情况。为了解决这个问题,可以采用为上传文件自动命名的方式。为了防止重名,自动命名可以采用如下的格式:IP地址+时间戳+三位随机数。
实例3
定义取得IP时间戳的操作类(IPTimeStamp.java)
1 package cn.mldn.lxh.util ; 2 import java.text.SimpleDateFormat ; 3 import java.util.Date ; 4 import java.util.Random ; 5 public class IPTimeStamp { 6 private SimpleDateFormat sdf = null ; 7 private String ip = null ; 8 public IPTimeStamp(){ 9 } 10 public IPTimeStamp(String ip){ 11 this.ip = ip ; 12 } 13 public String getIPTimeRand(){ 14 StringBuffer buf = new StringBuffer() ; 15 if(this.ip != null){ 16 String s[] = this.ip.split("\\.") ; 17 for(int i=0;i<s.length;i++){ 18 buf.append(this.addZero(s[i],3)) ; 19 } 20 } 21 buf.append(this.getTimeStamp()) ; 22 Random r = new Random() ; 23 for(int i=0;i<3;i++){ 24 buf.append(r.nextInt(10)) ; 25 } 26 return buf.toString() ; 27 } 28 public String getDate(){ 29 this.sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") ; 30 return this.sdf.format(new Date()) ; 31 } 32 public String getTimeStamp(){ 33 this.sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS") ; 34 return this.sdf.format(new Date()) ; 35 } 36 private String addZero(String str,int len){ 37 StringBuffer s = new StringBuffer() ; 38 s.append(str) ; 39 while(s.length() < len){ 40 s.insert(0,"0") ; 41 } 42 return s.toString() ; 43 } 44 public static void main(String args[]){ 45 System.out.println(new IPTimeStamp("192.168.1.1").getIPTimeRand()) ; 46 } 47 }
上传表单(demo3_1.html)
1 <html> 2 <head> 3 <title>混合表单</title> 4 </head> 5 <body> 6 <form action="demo3_2.jsp" method="post" enctype="multipart/form-data"> 7 姓名:<input type="text" name="uname"><br> 8 照片:<input type="file" name="pic"><br> 9 <input type="submit" value="上传"> 10 <input type="reset" value="重置"> 11 </form> 12 </body> 13 </html>
自动命名在上传操作页中不能像之前那样直接使用save()方法保存,而要取得一个具体的上传文件对象才可以保存,而且由于上传文件时文件的后缀需要统一,所以可以使用getFileExt方法取得后缀。
接收表单文本、图片并保存(demo3_2.jsp)
1 <%@ page contentType="text/html" pageEncoding="GBK"%> 2 <%@ page import="org.lxh.smart.*"%> 3 <%@ page import="cn.mldn.lxh.util.*"%> 4 <html> 5 <head> 6 <title>混合表单</title> 7 </head> 8 <body> 9 <% 10 request.setCharacterEncoding("GBK") ; 11 %> 12 <% 13 SmartUpload smart = new SmartUpload() ; 14 smart.initialize(pageContext) ; // 初始化上传操作 15 smart.upload() ; // 上传准备 16 String name = smart.getRequest().getParameter("uname") ; 17 IPTimeStamp its = new IPTimeStamp(request.getRemoteAddr()) ; // 取得客户端的IP地址 18 String ext = smart.getFiles().getFile(0).getFileExt() ; // 扩展名称 19 String fileName = its.getIPTimeRand() + "." + ext ; 20 smart.getFiles().getFile(0).saveAs(this.getServletContext().getRealPath("/")+"upload"+java.io.File.separator + fileName) ; 21 %> 22 <h2>姓名:<%=name%></h2> 23 <img src="../upload/<%=fileName%>"> 24 </body> 25 </html>
上述程序在进行上传操作时,使用了IPTimeStamp类完成文件的自动命名操作,由于SmartUpload可以同时接收多个上传文件,所以此时通过smart.getFiles().getFile(0).getFileExt()取得第一个上传文件的文件后缀,在与之前IPTimeStamp类生成的文件名称一起拼凑出一个新的文件名,由于此事要用新的文件名称保存上传文件,所以要通过smart.getFiles().getFile(0).saveAs()方法进行手工保存。
可以通过正则表达式限制文件后缀:
1 if(smart.getFiles().getFile(0).getFileName().matches("^\\w+.(jpg|gif)$")) { 2 3 }
4 批量上传
实例4
上传表单(demo4_1.html)
1 <html> 2 <head> 3 <title>混合表单</title> 4 </head> 5 <body> 6 <form action="demo4_2.jsp" method="post" enctype="multipart/form-data"> 7 照片1:<input type="file" name="pic1"><br> 8 照片2:<input type="file" name="pic2"><br> 9 照片3:<input type="file" name="pic3"><br> 10 <input type="submit" value="上传"> 11 <input type="reset" value="重置"> 12 </form> 13 </body> 14 </html>
如果要完成批量上传,则肯定要是使用循环的方式进行,那么就必须通过如下方法取得上传数量。
取得全部上传文件数量:smart.getFiles().getCount()
1 <%@ page contentType="text/html" pageEncoding="GBK"%> 2 <%@ page import="org.lxh.smart.*"%> 3 <%@ page import="cn.mldn.lxh.util.*"%> 4 <html> 5 <head> 6 <title>混合表单</title> 7 </head> 8 <body> 9 <% 10 request.setCharacterEncoding("GBK") ; 11 %> 12 <% 13 SmartUpload smart = new SmartUpload() ; 14 smart.initialize(pageContext) ; // 初始化上传操作 15 smart.upload() ; // 上传准备 16 String name = smart.getRequest().getParameter("uname") ; 17 IPTimeStamp its = new IPTimeStamp(request.getRemoteAddr()) ; // 取得客户端的IP地址 18 for(int x=0;x<smart.getFiles().getCount();x++){ 19 String ext = smart.getFiles().getFile(x).getFileExt() ; // 扩展名称 20 String fileName = its.getIPTimeRand() + "." + ext ; 21 smart.getFiles().getFile(x).saveAs(this.getServletContext().getRealPath("/")+"upload"+java.io.File.separator + fileName) ; 22 } 23 %> 24 </body> 25 </html>
程序运行后,会在根目录下的upload文件夹中发现已经同时保存了3个上传文件,并且文件名称没有重复。