读书人

servlet文件下传上载

发布时间: 2012-09-24 13:49:41 作者: rapoo

servlet文件上传下载

一、文件上传入门

1. 应用:

?用户上传头像、上传图片、邮件上传附件等

2. 页面表单的实现

??? 文件上传表单和普通表单有两个区别

??? 1) 需要文件上传字段? <input type=”file” />

??? 2) form 表单的 enctype 属性需要指定为 multipart/form-data

3. 服务器端解析request

??? 在 Servlet 中通过 request.getInputStream 获得表单上传数据,会发现数据是分段发送的

由于自己写程序解析有难度,我们可以使用Apache 开发的开源组件Commons-fileupload

需要导入 jar 包Commons-fileupload 和Commons-io

4 . UploadServlet 中处理文件上传程序

?

// 1. 创建工厂类

DiskFileItemFactory factory = new DiskFileItemFactory();

// 2. 创建FileUpload对象

ServletFileUpload upload = new ServletFileUpload(factory);

// 3. 判断是否是上传表单

boolean b = upload.isMultipartContent(request);

if(!b) {

??? // 不是文件上传

request.setAttribute("message", "对不起,不是文件上传表单!");

request.getRequestDispatcher("/message.jsp").forward(request, response);

??? return;

}

// 是文件上传表单

// 4. 解析request,获得FileItem项

List<FileItem> fileitems = upload.parseRequest(request);

// 5. 遍历集合

for(FileItem item : fileitems) {

??? // 判断是不是普通字段

if(item.isFormField()) {

??? String name = item.getFieldName();

??? String value = item.getString();

??? // 手工的转换了

??? value = new String(value.getBytes("iso-8859-1"),"utf-8");

??? System.out.println(name + "=" + value);

} else {

??? // 文件上传字段

??? // 获得文件名

??? String filename = item.getName();

??? System.out.println(filename);

??? filename = filename.substring(filename.lastIndexOf("\\")+1);

???

??? System.out.println(filename);

??? // 创建文件

??? ServletContext context = getServletContext();

??? String dir = context.getRealPath("WEN-INF/upload");

??? File file = new File(dir, filename);

??? file.createNewFile();

???

??? // 获得流,读取数据写入文件

??? InputStream in = item.getInputStream();

??? FileOutputStream fos = new FileOutputStream(file);

???

??? int len;

??? byte[] buffer = new byte[1024];

??? while((len=in.read(buffer))>0)

?????? fos.write(buffer,0,len);

??? fos.close();

??? in.close();

??? item.delete();??? // 删除临时文件

}

?

?

二、 文件上传处理细节

1. 中文乱码问题

??? 1) 文件名中文乱码问题,解决办法: 告诉文件上传组件以什么编码方式来解码文件名

?????? ServletUpload.setCharacterEncoding(“utf-8”);

?????? request. setCharacterEncoding(“utf-8”);

????

??? 2) 普通字段中文乱码问题

?????? fileitem.getString(“utf-8”);??????

?

2. ? 临时文件

??? 对于大文件不能缓存在内存,需要缓存到硬盘,为了方便管理,我们需要设置临时文件存放目录

??? // 设置临时文件的存放位置

factory.setRepository(new File("d:/temp"));

?

??? 文件上传完毕需要删除临时文件,否则会导致服务器存在两份上传文件

// 注意,需要先将流进行关闭,否则会导致临时文件无法删除

out.close();

in.close();

// 删除临时文件

fileitem.delete();

?

3. 文件存放目录

??? 1) 目录需要隐藏,禁止外界直接访问

??? 2) 文件名需要保证不重复

??? 3) 文件应该分目录存放

?

三、上传进度条

1. 实现进度监听

??? 需要实现对文件上传进度的监听,需要给FileUpload 对象添加 ProgressListener

??? 在upload方法中对与进度相关的数据进行处理

??? upload.setProgressListener(new ProgressListener() {

??? long num = 0;

??? public void update(long bytesRead, long contentLength, int items) {

??????

??? ??? ??? long progress = bytesRead*100/contentLength;

?????? ??? if(progress==num)

?????????? ??? return;

?????? ??? num = progress;

?????? ??? System.out.println("上传进度:" + progress + "%");

??????

??? ??? //? request.getSession().setAttribute("progress", progress);

??? ??? }

??? });

?

2. 在 jsp 页面显示进度

??? 实验:?

??? 1) 使用 iframe 发送请求, 请求一个Servlet, 在Servlet 中返回响应,发送自增的num

?????? 此时会发现 iframe 会不停第想Servlet发送请求

??? 2) 点击文件上传按钮后,iframe立刻停止刷新,直至上传完毕页面跳转至新页面

??? 3)为了观察实验结果,将form 的 target 指定为 iframe, UploadServlet回送上传完毕的结果

??? 4) 出现上述问题的原因,浏览器不支持多线程同时访问服务器只能同时发送一个请求,

?????? 这样的访问方式为同步访问

??? 5) 要在文件上传的同时在iframe中实现进度访问,就需要ie浏览器与服务器进行异步交互

?????? 此时就需要 XMLHttpRequest 对象

?????? 在javascript中可以直接使用XMLHttpRequest 对象与服务器进行异步通信

?????? 获得XmlHttpRequest 对象的方式有两种

?????? ie7以上版本

?????? var xhr = null;

?????? if(window.XMLHttpRequest)

?????????? xhr = new XMLHttpRequest();

?????? ie7以下版本

?????? if(window.ActiveXObject)

?????????? xhr = new ActiveXObject(“Microsoft.XMLHTTP”);

??????

?????? 获得对象后需要调用open方法输入请求地址

?????? 注意请求方式, 地址的输入, 并且需要设置为true 指定异步访问该地址

?????? xhr.open(“get”,”/upload/servlet/UploadServlet”, false)

??????

?????? // 调用send 方法发送请求,post方式需要发送消息体,get方式则不用直接传入null值

?????? xhr.send(null);

??????

?????? // 访问 responseText 属性获得 Servlet 回送的数据

?????? document.write(xhr.responseText);

?

四、 api方法

1. DiskFileItemFactory 对象

??? 设置缓冲区大小,字节为单位,默认为10K,一般不用修改

??? factory.setSizeThreshold(1000);

??? 设置临时文件存放目录

??? factory.setRepository(file);

?

2. ServletFileUpload 对象

??? 判断是否为文件上传表单

??? boolean b = upload.isMultipartContent(request);

?? 解析request对象

?? List<FileItem> list = upload.parseRequest(request);

?? 设置上传文件的最大值

??? setFileSizeMax(long?fileSizeMax)

??? 设置上传文件总量的最大值

??? setSizeMax(long?sizeMax)

??? 设置编码格式

??? setHeaderEncoding(java.lang.String?encoding)

??? 注册进度监听器

??? setProgressListener(ProgressListener?pListener)

?

3. FileItem 对象

??? 获得表单字段的属性名

??? item.getFieldName();

??? 获得普通字段的值

??? item.getString(charsetName)

??? 获得文件上传字段的文件名

??? item.getName()

??? 获得文件上传的流

??? item.getInputStream()

??

?

1 楼 debbykindom 2011-10-25 好,王力宏

读书人网 >软件架构设计

热点推荐