看到局部刷新,大家联想到的肯定是Ajax,但实际上,Ajax是没有办法实现文件上传的局部刷新的。由于安全性的需要,JavaScript代码是不能访问客户端文件系统,所以通过XMLHttpRequest的请求参数是无法得到上传文件的内容的,只能得到文件名。
那么我们又是怎样实现文件上传局部刷新的呢?其实我们再上传文件的时候采用的还是同步方式,为了不刷新整个页面,我们需要用到隐藏的iframe,我们在页面上增加一个隐藏的<iframe>元素,该元素将会作为提交表单的target。
文件上传要求表单的提交方式是POST,另外需要设置表单的MIME编码enctype="multipart/form-data"。页面代码如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>upload</title> </head> <body> <form action="UploadServlet" method="post" enctype="multipart/form-data" target="hideframe"> <input type="file" name="file"/> <input type="submit" value="上传"/> </form> <iframe name="hideframe" style="display:none"></iframe> </body> </html>
表单的target属性对应与<iframe>的name属性,这样就能够只更新<iframe>元素,从而实现无刷新的文件上传。
上传文件用到一个开源项目:commons-fileupload,将其添加到应用的WEB-INF/lib路径下即可。上传的Servlet代码如下:
public class UploadServlet extends HttpServlet { /** * 上传文件 */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); // 工厂 DiskFileItemFactory factory = new DiskFileItemFactory(); // 解析器 ServletFileUpload sfu = new ServletFileUpload(factory); // 解析,得到List try { List<FileItem> list = sfu.parseRequest(request); FileItem fi = list.get(0); //得到文件保存的路径 String fileName = fi.getName();//获取上传的文件名称 String root = this.getServletContext().getRealPath("files/upload/"); //创建文件 File destFile = new File(root, fileName); //写数据 fi.write(destFile); out.write("<script type='text/javascript'> alert('文件上传成功') </script>"); } catch (FileUploadException e) { e.printStackTrace(); out.write("<script type='text/javascript'> alert('文件上传不成功,请重试') </script>"); } } }
例子写得比较简单,在实际上传处理中,FileItem还有以下常用方法
boolean isFormField():是否为普通表单项!返回true为普通表单项,如果为false即文件表单项;
String getFieldName():返回当前表单项的名称;
String getString(String charset):返回表单项的值;
long getSize():返回上传文件的字节数;
InputStream getInputStream():返回上传文件对应的输入流
要注意一点,request.getParametere("xxx")这个方法在表单为enctype="multipart/form-data"时作废,它只会返回null。所以要得到普通表单项的值,要使用上面说到的getString(String charset)方法。
Author:立礼
Sign:人生不要有太多的幻想,而要有更多的行动。