jsp+servlet实现文件的上传和下载 运用了Apache Commons组件

开门见山,我们直接来看jsp代码:

<form action="/upload/upload" enctype="multipart/form-data" method="post"> <input type="file" name="filename" /><br> <input type="submit" value="上传"/><br> </form> ${msg }

这是一个form表单,enctype中的值和用别的组件或流上传时的值是一样的都是:multipart/form-data.  还有就是method值必须为post。file表单我就不再多说,都懂得。

下面来看servlet代码实现文件上传:

import java.io.File; import java.io.IOException; 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.FileUploadBase; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import cn.itcast.commons.CommonUtils; public class upload extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); //得到工厂 DiskFileItemFactory factory = new DiskFileItemFactory(10*1024,new File("F:/temp")); //得到解析器 ServletFileUpload sfu = new ServletFileUpload(factory); try { //限制文件的大小,必须在解析得到List之前调用,否则限制无效 //sfu.setFileSizeMax(100); //解析得到List List<FileItem> list = sfu.parseRequest(request); //得到表单项 FileItem fl = list.get(0); /** * 1.得到文本保存的路径 */ String root = this.getServletContext().getRealPath("/WEB-INF/files/"); /** * 2.生成二层目录 * 1) 得到文件名称 * 2) 得到hashcode * 3) 转化成16进制 * 4) 获取前两个字符来生成目录 */ String filename = fl.getName(); //处理文件名的绝对路径问题 int index = filename.lastIndexOf("\\"); if(index != -1) { filename = filename.substring(index+1); } //给文件名添加uuid前缀,处理文件同名问题 String savename = CommonUtils.uuid() + "_" +filename; //得到hashcode int hCode = savename.hashCode(); String hex = Integer.toHexString(hCode); //获取hex的前两个字母,与root连接在一起,生成一个完整的路径 File dirFile = new File(root ,hex.charAt(0)+"\\" +hex.charAt(1) ); //创建目录链 dirFile.mkdirs(); //创建目录文件 File destFile = new File(dirFile,savename); //保存 fl.write(destFile); } catch (Exception e) { if(e instanceof FileUploadBase.FileSizeLimitExceededException) { request.setAttribute("msg", "您上传的文件超出了100K."); request.getRequestDispatcher("index.jsp").forward(request, response); } } } }

因为在表单实现上传时,servlet中的request得到传输值得方法已经不能用了(作废),但是request还可以设置字符编码,因为在commons组件中它自己会调用这个方法request.setCharacterEncoding("utf-8"); request设置字符编码的方法有两种,上面是第一种,第二种是servletFileUpload.setHeaderEncoding("utf-8");这种优先级高于上一种,通常使用第一种。

下面咱们来一起学习文件上传的三步骤:
①得到工厂 DiskFileItemFactory factory = new DiskFileItemFactory();
②得到解析器 ServletFileUpload sfu = new ServletFileUpload(factory);
③解析得到List List<FileItem> list = sfu.parseRequest(request);

在学习文件上传三步骤之前咱们先来了解一下上传文件前系统生成的文件头(表单头):

POST /upload/upload HTTP/1.1 Accept: text/html, application/xhtml+xml, */* X-HttpWatch-RID: 14415-10046 Referer: http://localhost:8080/upload/ Accept-Language: zh-CN User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko Content-Type: multipart/form-data; boundary=---------------------------7df13a1920408 Accept-Encoding: gzip, deflate Host: localhost:8080 Content-Length: 733114 DNT: 1 Connection: Keep-Alive Cache-Control: no-cache Cookie: JSESSIONID=100387FBC7C815A0A951F1ABE69D7D26 -----------------------------7df13a1920408 Content-Disposition: form-data; name="filename"; filename="struts灏忛」鐩?zip" Content-Type: application/x-zip-compressed

这是用httpwatch捕获到的文件上传时提交的代码,下面来分析一下这段代码:
我们需要了解的就是下面这几行代码:
Content-Type: multipart/form-data; boundary=---------------------------7df13a1920408
Accept-Encoding: gzip, deflate
Content-Length: 733114

Content-Disposition: form-data; name="filename"; filename="struts灏忛」鐩?zip"
Content-Type: application/x-zip-compressed
第①个代码中Accept-Encoding: gzip, deflate是指接受的文件是zip格式,长度为733114字节
第②个代码中Content-Disposition 中的name是指form表单中name设置的值,filename是指上传的文件名;
关于文件的各种信息,commons会自己获取,我们只需要从commons提供的方法中获取文件名和文件的大小即可。

下面我们来学习文件上传三步骤:
①得到工厂 DiskFileItemFactory factory = new DiskFileItemFactory();
该代码表示得到文件上传的工厂
②得到解析器 ServletFileUpload sfu = new ServletFileUpload(factory);
该代码用来得到解析器 来解析工厂的内容
③解析得到List List<FileItem> list = sfu.parseRequest(request);
这个是解析request对象来得到file文件的各种内容(包含文件名和大小等)

FileItem fl = list.get(0);得到表单项,一般情况下:一个表单可能有多个表单项,比如上传者姓名、上传时间等(都是一个输入框形势)。这句代码就是得到上传文件的表单项。

/**
* 1.得到文本保存的路径
*/

String root = this.getServletContext().getRealPath("/WEB-INF/files/");
上面的代码是得到文件上传的根路径,完成文件上传前,必须在WEB-INF目录下创建一个files文件夹,表示把所有上传的文件都放在该文件夹中,这样别人就不能访问你的资源。

一般文件上传会遇到重名问题,如果不进行处理,后者会把前者覆盖掉。所以接下来我们来学习如何处理该问题:

/**
* 2.生成二层目录
* 1) 得到文件名称
* 2) 得到hashcode
* 3) 转化成16进制
* 4) 获取前两个字符来生成目录
*/
得到文件名
String filename = fl.getName();

//处理文件名的绝对路径问题
int index = filename.lastIndexOf("\\");

if(index != -1)
{
filename = filename.substring(index+1);
}

//给文件名添加uuid前缀,处理文件同名问题
String savename = CommonUtils.uuid() + "_" +filename;

//得到hashcode
int hCode = savename.hashCode();
hashcode转化为16进制字符串
String hex = Integer.toHexString(hCode);

//获取hex的前两个字母,与root连接在一起,生成一个完整的路径
File dirFile = new File(root ,hex.charAt(0)+"\\" +hex.charAt(1) );

//创建目录链
dirFile.mkdirs();

//创建目录文件
File destFile = new File(dirFile,savename);


//保存
fl.write(destFile);

我们用生成二层目录和文件名前加uuid随机码来处理该问题,生成二层目录主要来解决文件过多使服务器变慢的问题。

这就完成了文件上传的所有工作(任何文件都能上传,中文乱码第一句就处理了)。
下面是commons组件需要的文件包:
commons-fileupload-1.2.2.jar
commons-io-1.4.jar
commons-beanutils-1.8.3.jar
commons-logging-1.1.1.jar
需要的可以网上下载一下,来学习一下jsp文件上传


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值