文件上传:html
1.所须要的包:前端
commons-fileupload-1.2.1.jarjava
commons-io-1.4.jarweb
2.浏览器端:数据库
1>.请求方式必须是 postapache
2>.须要使用组件<input type="file" name="f">浏览器
3>.表单必须设置encType="multipart/form-data"安全
4>.上传文件的input 中,name属性必需要填写,否则不会上传. 服务器
<form action="${pageContext.request.contextPath}/upload2" method="post" enctype="multipart/form-data"> <input type="file" name="f"> <input type="submit" value="上传"> <form/>
3.服务器端:app
能够经过request对象,获取InputStream,能够将浏览器提交的全部请求正文读取到。
4.核心类的使用:
1.DiskFileItemFactory 用于设置文件上传时,缓冲区大小以及临时文件存储位置.
1 能够设置文件上传缓冲区大小
factory.setSizeThreshold(1024*1024); //设置为1m 默认是10k
2能够设置临时文件存储位置
File temp=new File(this.getServletContext().getRealPath("/temp"));
factory.setRepository(temp); //能够指定临时文件存储位置,默认是系统的临时文件存储位置
2.ServletFileUpload 它的做用是真正完成解析数据操做上传类
1.pareRequest(HttpServletRequest request)
获得全部的上传信息,将每一部分映射成FileItem对象.
2.isMultipartContent(HttpServletRequest request)
这个方法返回值是boolean,它是用于判断当前表单是不是一个上传的表单,
简单说,就判断它的encType的值是不是 multipart/form-data.
3.setHeaderEncoding(String encoding)
用于解决上传文件名称中文乱码问题
4.能够设置上传文件大小,若是超过设置大小.将会抛出异常(默认没有最大值)
void setFileSizeMax(long fileSizeMax) 设置单个文件上传大小
void setSizeMax(long sizeMax) 设置总文件上传大小
3.FileItem 它表明的是每个上传项(其时就是表单中的每个组件)
1.isFormField()
这个方法返回的是boolean类型,
它是判断当前组件是不是上传组件 简单说,就是判断type="file",
若是返回true,表明不是上传组件,返回false,表明是上传组件
2.getName()
获取非上传组件的上传文件的名称,若是是非上传组件,返回的是null
3.getFieldName()
获取组件名称,提交的键
4.getString()
获取非上传组件的value值,
经过它也能够获取上传的文件内容,可是,使用它获取不合适。
若是使用了commons-fileupload进行文件上传,而上传表单中包含了
非上传组件,获取其值,不能使用request获取.
getString()有一个重载的方法 getString(String encoding)能够解决乱码问题
问题:使用getString()去获取上传文件内容不合适,那么怎样操做?
基本操做:
经过FileItem.getInputStream();能够获取一个输入流,这个输入流就能够读取出上传文件内容。
InputStream is = item.getInputStream(); // 用于读取上传文件内容的输入流.
FileOutputStream fos = new FileOutputStream(
"d:/upload/" + filename);
int len = -1;
byte[] b = new byte[1024 * 10];
while ((len = is.read(b)) != -1) {
fos.write(b, 0, len);
fos.flush();
}
fos.close();
is.close();
能够使用IOUtils工具完成文件copy操做
IOUtils.copy(is, fos);
5.delete方法
它是用于上传完成后,删除临时文件的
4.注意问题:
1>关于文件上传时文件名称包含中文的乱码问题?
调用ServletFileUpload的setHeaderEncoding方法解决
2>普通表单字段提交时,中文乱码问题?
FileItem的 getString方法返回提交的值.经过参数来设置解码码表
例如: getString("UTF-8");
3>如何设置上传文件大小限制?
调用ServletFileUpload的setSizeMax(总大小)
setFileSizeMax(每一个大小)方法
4>上传文件后,咱们应该把文件保存到什么位置?
1.上传以后,客户端直接可以访问到的地方. WEBRoot下
2.上传后其余用户不能直接访问
放到webRoot之外的文件夹. WEB-INF(安全目录)下或硬盘其余位置 .例如 d:/xxx
5>上传文件时,该使用什么名字将文件保存?
文件名称不能使用用户命名的名称.
用户命名的名称咱们须要保存到数据库中,在下载时使用.
6>不是用用户命名的名称,咱们以什么名称保存文件(不能重复)?
UUID
登陆用户名+当前系统毫秒数 (只容许单文件上传,一个请求只能上传一个文件)
7>如何得到用户命名的文件名?
getName方法便可得到文件名.
IE浏览器中,会把文件的在客户端的完整路径传过来.须要截取.
其余浏览器只会文件名称传过来.直接使用,无需截取.
8>为了防止同一个目录下方上传文件数量过多,思考如何解决?
/upload/2016/03/27/xxxx 使用当前日期做为子文件夹名称
当前登陆用户的用户名做为文件夹名称(不推荐)
实例:
upload.jsp(前端仅贴出相关提交的代码)
<!-- 1. 表单必须是post提交. 2. 修改enctype属性 . EncodeType 请求正文内容类型. application/x-www-form-urlencoded (默认值:用于提交文本类型内容). multipart/form-data (多段式提交) 3. 文件上传时,需使用 input type=file 组件 注意: 该组件必定要设置name属性. --> <body> <form action="/upload/AServlet" method="post" enctype="multipart/form-data"> 用户名:<input type="text" name="username"/><br/> <input type="file" name="file1" /><br/> <input type="file" name="file2"/> <input type="submit" value="提交"> </form> </body>
2.Aservlet.jsp
package cn.test.upload; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.UUID; 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.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.IOUtils; public class AServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.建立解析器配置工厂 //DiskFileItemFactory:用于设置文件上传时,缓冲区的大小以及临时文件的存储位置 DiskFileItemFactory factory = new DiskFileItemFactory(); //2.根据配置工厂的配置建立解析器类 //ServletFileUpload:真正完成解析上传数据的操做类 ServletFileUpload upload = new ServletFileUpload(factory); //3.判断是否为多段式方式提交,也就是判断它的encType的值是不是 multipart/form-data if(!upload.isMultipartContent(request)){ throw new RuntimeException("您的表单提交方式错误"); } //设置多段式每一段段头的编码表 upload.setHeaderEncoding("UTF-8"); //FileItem:表明的就是每个上传项,其实就是表单中的每个组件 List<FileItem> list=null; //3.调用解析方法,解析request对象 try { list = upload.parseRequest(request); }catch (FileUploadException e) { e.printStackTrace(); throw new RuntimeException("解析request对象失败!"); } if(list!=null){ for(FileItem item:list){ //判断item为普通文本提交段 if(item.isFormField()){ //得到普通文本提交的键 String key = item.getFieldName(); //得到普通文本提交的值,使用item.getString()的重载方法,解决中文乱码问题 String value = item.getString("UTF-8"); System.out.println(key+":"+value); } //处理文件上传段 else{ //获取上传的文件名 //String name = item.getName(); //System.out.println(name); InputStream is = item.getInputStream(); //将文件保存到upload目录下(文件名称不能重复,不能存储在单一文件夹下) //生成uuid文件名称 String uuid = UUID.randomUUID().toString(); //使用日期进行分目录 //得到upload目录所在的绝对路径 String dirPath = getServletContext().getRealPath("/upload"); //根据当前时间,得到时间路径 Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/"); String datePath = sdf.format(date); //检查当前时间目录结构是否存在,若是不存在则建立 File file = new File(dirPath+datePath); if(!file.exists()){ file.mkdirs(); } // InputStream in = item.getInputStream(); FileOutputStream out = new FileOutputStream(dirPath+datePath+uuid); IOUtils.copy(in, out); //释放资源,删除临时文件 out.close(); in.close(); item.delete(); } } } } }
文件下载
1.文件下载方式
1> 直接将待下载文件放到webRoot文件夹或子文件夹下.
2>须要控制资源的下载.在下载前要通过逻辑处理.
将资源放到用户不能直接访问的地方. 例如: WEB-INF 或 d:/upload
2.下载文件名称中文乱码问题
response.setHeader("content-disposition", "attachment;filename="+ filename);
这段代码中的filename是指定下载文件时的名称
对于IE浏览器,它要求必须给一个UTF-8码
对于firefox浏览器,它要求必须给一个base64编码
if (agent.contains("MSIE")) { // IE浏览器 filename = URLEncoder.encode(filename, "utf-8"); filename = filename.replace("+", " "); } else if (agent.contains("Firefox")) { // 火狐浏览器 BASE64Encoder base64Encoder = new BASE64Encoder(); filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; } else { // 其它浏览器 filename = URLEncoder.encode(filename, "utf-8"); }
文件下载实例:
1.DownLoadServlet.java
import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.IOUtils; public class DownloadServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.得到请求的文件名 String fileName = request.getParameter("name"); fileName = new String(fileName.getBytes("ISO-8859-1"),"UTF-8"); //2.设置content-type头|content-disposition头 response.setContentType(getServletContext().getMimeType(fileName)); response.setHeader("content-disposition","attachment;filename="+DownloadUtils.encode(fileName, request)); //3.根据参数指定的文件,找到对应的文件资源流 InputStream is = getServletContext().getResourceAsStream("/WEB-INF/"+fileName); //4.得到向浏览器输出的流 ServletOutputStream os = response.getOutputStream(); //5.将两个流对接 IOUtils.copy(is, os); //6.关闭资源 is.close(); os.close(); } }
2.DownLoadUtils.java
import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import javax.servlet.http.HttpServletRequest; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; public class DownloadUtils { public static String encode(String fileName,HttpServletRequest request){ //1.得到浏览器的类别 String agent = request.getHeader("User-Agent"); //2.判断浏览器类型 if(agent.contains("Firefox")){ //火狐浏览器=>按照base64进行编码 BASE64Encoder base64Encoder = new BASE64Encoder(); try { fileName = "=?utf-8?B?" + base64Encoder.encode(fileName.getBytes("utf-8")) + "?="; } catch (UnsupportedEncodingException e) { e.printStackTrace(); } }else{ //非火狐浏览器=>按照urlencoded编码方式编码 try { fileName = URLEncoder.encode(fileName,"UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } //3.返回编码后的结果 return fileName; } }
3.download.jsp
<body> <a href="/download/DownloadServlet?name=top.csv">下载top.csv文件</a><br/> <a href="/download/DownloadServlet?name=走遍中国.JPG">下载图片_走遍中国</a><br/> <a href="/download/DownloadServlet?name=原点.mp3">下载原点.mp3</a> </body>