J2EE初级学习之寒假进阶——文件上传和下载
2018-03-04 13:35
381 查看
上传
1.上传对表单的限制
method=”post”enctype=”multipart/form-data”
表单中需要添加文件表单项:
<input type="file" ...name="xxx"/>
2.上传对Servlet的限制
request.getParameter(“xxx”);这个方法在表单为enctype=”multipart/form-data”时,它作废了。它永远返回null举例说明:
<form action="xxx" method="post" enctype="multipart/form-data">
用户名:
<input type="text" name="username"/><br>
照 片:
<input type="file" name="picture" /><br> <input type="submit" value="上传" /> </form>
这时用户名的数据也无法通过getParameter接收!!!
ServletInputStream request.getInputStream();包含整个请求的体!
多部件表单的体:
1.分隔出多个部件,即一个表单一个部件。
2.一个部件中自己包含请求头和空行,已经请求体
3.普通表单项:
1个头:Content-Disposition:包含name=”xxx”,即表单名称
体就是表单项的值
4.文件表单项:
2个头:
* Content-Disposition:包含name=”xxx”,即表单名称;还有一个filename=”xxx”,表示上传文件的名称
* Content-Type:它是上传文件的MIME类型,例如:image/pjpeg,表示上传的是图片,图上中jpg扩展名的图片
体就是上传文件的内容
commons-fileupload
commons-fileupload-1.2.2.jar
commons-io.jar
这个小组件,它会帮我们解析request中的上传数据,解析后的结果是一个表单项数据封装到一个FileItem对象中。我们只需要调用FileItem的方法即可!
1.上传三步
相关类: * 工厂:DiskFileItemFactory * 解析器:ServlrtFileUpload * 表单项:FileItem 1)创建工厂:DiskFileItemFactory factory = new DiskFileItemFactory(); 2)创建解析器:ServlrtFileUpload sfu = new ServlrtFileUpload(factory); 3)使用解析器来解析request,得到FileItem集合:List<FileItem> fileItemList = sfu.parseRequest(request);
2.FileItem
* boolean isFormField():是否为普通表单项!返回true为普通表单项,如果为false即文件表单项! * String getFieldName():返回当前表单项的名称; * String getString(String charset):返回表单项的值; * String getName():返回上传的文件名称 * long getSize():返回上传文件的字节数 * InputStream getInputStream():返回上传文件对应的输入流 * void write(File destFile):把上传 4000 的文件内容保存到指定的文件中。 * String getContentType();
上传的细节:
1.文件必须保存到WEB-INF文件下!
目的是不让浏览器直接访问到!2.文件名称相关问题
有的浏览器上传的文件名是绝对路径,这需要切割! (C:\files)baibing.jpg,前面的不需要String filename = fileItem2.getName();
int index = filename.lastIndexOf(“\”); “//”这是表示一条斜杠
if(index != -1){
filename = filename.substring(index+1);
}
文件名乱码或者普通表单项乱码:request.setCharacterEncoding(“utf-8”);因为fileupload的内部会调用request.getCharacterEncoding();
request.setCharacterEncoding(“utf-8”); //优先级低
servletFileUpload.setHeadEncoding(“utf-8”); //优先级高
文件同名问题:我们需要为每个文件添加名称前缀,这个前缀保证不能重复。uuid
filename = CommonUtils.uuid() + “_” + filename;
3.目录打散
不能在一个目录下存放过多文件首字符打散:使用文件的首字母做为文件目录名称,例如abc.txt,那么我们把文件保存到a目录下,如果a目录不存在,那么创建之。
时间打散:使用当前日期做为目录。
Hash打散:
通过文件名称得到int值,即调用hashCode()
它int值转换成16进制0~9,A~F
获取16进制的前两位用来生成目录,目录为两层!例如:1B2C3D4E5F,/1/B/保存文件。
4.上传文件的大小限制:
* 单个文件大小限制
sfu.setFileSizeMax(100*1024);限制单个文件大小为100KB
上面的方法调用必须在解析开始之前!
如果上传的文件超出限制,在parseRequest()方法执行时会抛出异常!FileUploadBase.FileSizeLimitExceededException
* 整个请求所有数据大小限制
sfu.setSizeMax(1024*1024*100);限制整个表单的上传数据大小为100M
这个方法也是必须在解析开始前调用!
如果上传的文件超出限制,在parseRequest()方法执行时会抛出异常!FileUploadBase.FileSizeLimitExceededException
5.缓存大小与临时目录
* 缓存大小:超出多大,才向硬盘保存!默认为10KB
* 临时目录:向硬盘的什么位置保存
下载:
1.下载就是向客户端响应字节数据:
原来我们响应的都是html字节数据! 把一个文件变成一个字节数组,使用response.getOutputStream()来响应给浏览器!!!
2.下载的要求:
两个头一个流!Content-Type:你传递给客户端的文件是什么MIME类型,例如:image/pjpeg
通过文件名称调用ServletContext的getMimeType()方法,得到MIME类型!
Content-Disposition:它的默认值为inline,表示在浏览器窗口中打开!attachment(附件);filename=xxx
在filename=后面跟随的是显示在下载框中的文件名称!
流:要下载的文件数据!
自己new一个输入流即可!
下载的细节:
1.显示在下载块中的中文名称时,会出现乱码。* FireFox:Base64编码。
* 其他大部分浏览器:URL编码。
通用方案:filename = new String(filename.getBytes(“GBK”),”ISO-8859-1”);
上传的代码:
Upload1package com.TiHom.web.servlet; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.util.List; /** * @author TiHom */ public class Upload2Servlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); /* * 上传三步 * 1.得到工厂 * 2.通过工厂创建解析器 * 3.解析request,得到FileItem集合 * 4.遍历FileItem集合,调用其API完成文件的保存 */ DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload sfu = new ServletFileUpload(factory); try { List<FileItem> fileItemList = sfu.parseRequest(req); FileItem fileItem1 = fileItemList.get(0); FileItem fileItem2 = fileItemList.get(1); System.out.println("普通表单项演示:" + fileItem1.getFieldName() + "=" + fileItem1.getString("utf-8")); System.out.println("文件表单项演示:"); System.out.println("Content-Type:" + fileItem2.getContentType()); System.out.println("size:" + fileItem2.getSize()); System.out.println("filename:" + fileItem2.getName()); //保存文件 File destFile = new File("c:/aj.jpg"); fileItem2.write(destFile); } catch (Exception e) { throw new RuntimeException(e); } } }
Upload2
package com.TiHom.web.servlet; 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 javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.util.List; /** * @author TiHom */ public class Upload3Servlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); /* * 上传三步 */ //得到工厂 DiskFileItemFactory factory = new DiskFileItemFactory(); //得到解析器 ServletFileUpload sfu = new ServletFileUpload(factory); //限制单个文件大小为100KB sfu.setFileSizeMax(10*10*1024); sfu.setSizeMax(1024*1024*100); try { //解析得到list List<FileItem> fileItemList = sfu.parseRequest(req); //得到文件表单项 FileItem fileItem = fileItemList.get(1); //得到文件保存的路径 String root = this.getServletContext().getRealPath("/WEB-INF/files/"); /* * 生成二层目录 * 1).得到文件名称 * 2).得到hashCode * 3).转换成16进制 * 4).获取前两个字符用来生成目录 */ //获取上传的文件名称 String filename = fileItem.getName(); //处理文件名的绝对路径的问题 int index = filename.lastIndexOf("\\"); if(index != -1){ //证明有‘/’ filename = filename.substring(index+1); } //给文件名称添加uuid前缀,处理文件同名问题 String savename = CommonUtils.uuid() + "_" + filename; //得到hashCode int hCode = filename.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); //保存 fileItem.write(destFile); } catch (FileUploadException e) { //异常处理 if(e instanceof FileUploadBase.FileSizeLimitExceededException){ req.setAttribute("msg","您上传的文件超出了10MB!"); req.getRequestDispatcher("/form3.jsp").forward(req,resp); } } catch (Exception e) { e.printStackTrace(); } } }
下载代码:
DownLoadpackage com.TiHom.web.servlet; import org.apache.commons.io.IOUtils; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.FileInputStream; import java.io.IOException; /** * @author TiHom */ public class Download1Servlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /* * 两个头一个流 * 1.Content-Type * 2.Content-Disposition * 3.流:下载文件的数据 */ String filename = "文件的路径"; //为了使下载框中显示中文文件名称不乱码!filename那里应该不带盘符符号 String framename = CommonUtils.filenameEncoding(filename,req); //通过文件名称获取MIME类型 String contentType = this.getServletContext().getMimeType(filename); String contentDisposition = "attachment;filename=" 99d4 + framename; //一个流 FileInputStream in = new FileInputStream(filename); //设置头 resp.setHeader("Content-Type",contentType); resp.setHeader("Content-Disposition",contentDisposition); //获取绑定的客户端的流 ServletOutputStream out = resp.getOutputStream(); //把输入流中的数据写入到输出流中 IOUtils.copy(in,out); in.close(); } }
相关文章推荐
- 4000 J2EE初级学习之寒假进阶——JavaMail邮件
- 【J2EE核心开发学习笔记 012】Struts2文件的上传与下载
- J2EE初级学习之寒假进阶——动态代理和代理工厂
- J2EE初级学习之寒假进阶——装饰者模式
- J2EE初级学习之寒假进阶——类加载器
- 云计算学习笔记004---hadoop的简介,以及安装,用命令实现对hdfs系统进行文件的上传下载
- php学习笔记(十)文件的上传与下载
- 黑马程序员_学习日记71_723ASP.NET(文件上传下载、IsPostBack原理、页面生命周期)
- Struts2学习笔记之文件的上传与下载
- bboss mvc文件上传下载实战进阶
- 学习 PHP,第 1 部分: 注册帐户、上传需要批准的文件、并查看和下载已批准的文件
- struts 学习总结 ---- 文件上传与下载
- JavaWeb学习之道:文件上传和下载
- 【转载】struts 学习总结 ---- 文件上传与下载
- 学习笔记之 文件的上传和下载代码
- Spring3.0 入门进阶(5):文件的上传与下载
- 学习笔记:基础+文件操作(上传|下载)+面向对象+xml
- 文件的上传下载---struts2学习笔记
- 【小白笔记】PHP学习之路 (26) --文件上传与下载、配置
- Struts2学习笔记之文件的上传与下载