今天我们来学习Servlet文件上传下载
Servlet文件上传主要是使用了ServletInputStream读取流的方法,其读取方法与普通的文件流相同。
一.文件上传相关原理
第一步,构建一个upload.jsp文件
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form enctype="application/x-www-form-urlencoded" action="${pageContext.request.contextPath }/servlet/UploadServlet1" method="post"> <input type="text" name="name" value="name" /><br/> <div id="div1"> <div> <input type="file" name="photo" /> </div> </div> <input type="submit" name="上传" /><br/> </form> </body> </html>
第二步,构建一个servlet UploadServlet1.java
package com.zk.upload; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class UploadServlet1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name=request.getParameter("name"); String photo=request.getParameter("photo"); ServletInputStream inputstream=request.getInputStream(); int len=0; byte[] b=new byte[1024]; while((len=inputstream.read(b))!=-1){ System.out.println(new String(b,0,len)); } inputstream.close(); }
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletInputStream inputstream=request.getInputStream(); int len=0; byte[] b=new byte[1024]; while((len=inputstream.read(b))!=-1){ System.out.println(new String(b,0,len)); } inputstream.close(); } /** * Initialization of the servlet. <br> * * @throws ServletException if an error occurs */ public void init() throws ServletException { // Put your code here } }
最后执行UploadServlet1.java之后,输出上传文件的信息。
这里涉及到文件上传的相关原理,在我本地浏览器中调试显示信息如下:
这是一些有关文件上传的相关信息。
二.文件上传
接下来,我们开始进行文件上传的工作。
第一部,创建jsp
这里的form表单需要更改一下enctype属性,这个属性是规定在发送到服务器之前应该如何对表单数据进行编码。
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> </head> <body> <form enctype="multipart/form-data" action="${pageContext.request.contextPath }/servlet/UploadServlet2" method="post"> <input type="text" name="name" value="name" /><br/> <div id="div1"> <div> <input type="file" name="photo" /> </div> </div> <input type="submit" name="上传" /><br/> </form> </body> </html>
UploadServlet2.java
package com.zk.upload; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; 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.FileUploadBase; 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.FilenameUtils; public class UploadServlet2 extends HttpServlet { /** * Constructor of the object. */ public UploadServlet2() { super(); } /** * Destruction of the servlet. <br> */ public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } /** * The doGet method of the servlet. <br> * * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //优先级不高 request.setCharacterEncoding("UTF-8"); //要执行文件上传的操作 //判断表单是否支持文件上传 boolean isMultipartContent=ServletFileUpload.isMultipartContent(request); if(!isMultipartContent){ throw new RuntimeException("your form is not multipart/form-data"); } //创建一个DiskFileItemFactory工厂类 DiskFileItemFactory factory=new DiskFileItemFactory(); //创建一个ServletFileUpload核心对象 ServletFileUpload sfu=new ServletFileUpload(factory); //解决上传表单乱码的问题 sfu.setHeaderEncoding("UTF-8"); try { //限制上传文件的大小 //sfu.setFileSizeMax(1024); //sfu.setSizeMax(6*1024*1024); //解析requst对象,得到一个表单项的集合 List<FileItem> fileitems=sfu.parseRequest(request); //遍历表单项数据 for(FileItem fileItem:fileitems){ if(fileItem.isFormField()){ //普通表单项 processFormField(fileItem); } else{ //上传表单项 processUploadField(fileItem); } } } catch(FileUploadBase.FileSizeLimitExceededException e){ throw new RuntimeException("文件过大"); }catch (FileUploadException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void processUploadField(FileItem fileItem) { // TODO Auto-generated method stub //得到上传的名字 String filename=fileItem.getName(); //得到文件流 try { InputStream is=fileItem.getInputStream(); String dictory=this.getServletContext().getRealPath("/upload"); System.out.println(dictory); //创建一个存盘的路径 File storeDirecctory=new File(dictory);//既代表文件又代表目录 if(!storeDirecctory.exists()){ storeDirecctory.mkdirs();//创建一个指定目录 } //处理文件名 filename=filename.substring(filename.lastIndexOf(File.separator)+1); if(filename!=null){ filename=FilenameUtils.getName(filename); } //解决文件同名的问题 filename=UUID.randomUUID()+"_"+filename; //目录打散 //String childDirectory=makeChildDirectory(storeDictory);//2015-10- String childDirectory=makeChildDirectory2(storeDirecctory,filename); //System.out.println(childDirectory); //上传文件,自动删除临时文件 fileItem.write(new File(storeDirecctory,childDirectory+File.separator+filename)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } //上传表单项 private void processUploadField1(FileItem fileItem) { // TODO Auto-generated method stub //得到上传的名字 String filename=fileItem.getName(); //得到文件流 try { //得到文件流 InputStream is=fileItem.getInputStream(); String dictory=this.getServletContext().getRealPath("/upload"); System.out.println(dictory); //创建一个存盘的路径 File storeDictory=new File(dictory);//既代表文件又代表目录 if(!storeDictory.exists()){ storeDictory.mkdirs();//创建一个指定目录 } //处理文件名 filename=filename.substring(filename.lastIndexOf(File.separator)+1); if(filename!=null){ filename=FilenameUtils.getName(filename); } //解决文件同名的问题 filename=UUID.randomUUID()+"_"+filename; //目录打散 //String childDirectory=makeChildDirectory(storeDictory);//2015-10- String childDirectory2=makeChildDirectory2(storeDictory,filename); //System.out.println(childDirectory); //在storeDictory目录下创建完整的文件 //File file=new File(storeDictory,filename); //File file=new File(storeDictory,childDirectory+File.separator+filename); File file2=new File(storeDictory,childDirectory2+File.separator+filename); //通过文件输出流将上传的文件保存到磁盘 //FileOutputStream fos=new FileOutputStream(file); FileOutputStream fos2=new FileOutputStream(file2); int len=0; byte[] b=new byte[1024]; while((len=is.read(b))!=-1){ // fos.write(b,0,len); fos2.write(b,0,len); } //fos.close(); fos2.close(); is.close(); System.out.println("success"); //删除临时文件 fileItem.delete(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //目录打散 private String makeChildDirectory(File storeDictory) { // TODO Auto-generated method stub SimpleDateFormat sm=new SimpleDateFormat("yyyy-MM-dd"); String date=sm.format(new Date()); //创建目录 File file=new File(storeDictory,date); if(!file.exists()){ file.mkdirs(); } return date; } //目录打散 private String makeChildDirectory2(File storeDictory,String filename){ int hashcode=filename.hashCode(); System.out.println(hashcode); String code=Integer.toHexString(hashcode); String childDirectory=code.charAt(0)+File.separator+code.charAt(1); //创建指定目录 File file=new File(storeDictory,childDirectory); if(!file.exists()){ file.mkdirs(); } return childDirectory; } //普通表单项 private void processFormField(FileItem fileItem) { // TODO Auto-generated method stub String fieldname=fileItem.getFieldName(); try { String valuename=fileItem.getString("UTF-8"); // fieldname=new String(valuename.getBytes("iso-8859-1"),"utf-8"); System.out.println(fieldname+":"+valuename); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * The doPost method of the servlet. <br> * * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); //要执行文件上传的操作 //判断表单是否支持文件上传 boolean isMultipartContent=ServletFileUpload.isMultipartContent(request); if(!isMultipartContent){ throw new RuntimeException("your form is not multipart/form-data"); } //创建一个DiskFileItemFactory工厂类 DiskFileItemFactory factory=new DiskFileItemFactory(); //产生临时文件 factory.setRepository(new File("f:\temp")); //创建一个ServletFileUpload核心对象 ServletFileUpload sfu=new ServletFileUpload(factory); sfu.setHeaderEncoding("UTF-8"); try { //限制上传文件的大小 //sfu.setFileSizeMax(1024*1024*1024); //sfu.setSizeMax(6*1024*1024); //解析requst对象,得到一个表单项的集合 List<FileItem> fileitems=sfu.parseRequest(request); //遍历表单项数据 for(FileItem fileItem:fileitems){ if(fileItem.isFormField()){ //普通表单项 processFormField(fileItem); } else{ //上传表单项 processUploadField(fileItem); } } } catch(FileUploadBase.FileSizeLimitExceededException e){ //throw new RuntimeException("文件过大"); System.out.println("文件过大"); }catch (FileUploadException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * Initialization of the servlet. <br> * * @throws ServletException if an error occurs */ public void init() throws ServletException { // Put your code here } }
这里面加了文件大小限制、文件重命名、目录打散等方法。
最后,我们运行一下这个demo
我们在web-apps的目录下可以看到我们刚刚上传的文件
三.文件下载
现在我们进行文件下载
package com.zk.upload; import java.io.FileInputStream; import java.io.IOException; import java.io.PrintWriter; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class DownloadServlet1 extends HttpServlet { /** * Constructor of the object. */ public DownloadServlet1() { super(); } /** * Destruction of the servlet. <br> */ public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } /** * The doGet method of the servlet. <br> * * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置一个要下载的文件 String filename="a.csv"; filename=new String(filename.getBytes("UTF-8"),"iso-8859-1"); //告知浏览器要下载文件 response.setHeader("content-disposition", "attachment;filename="+filename); response.setContentType(this.getServletContext().getMimeType(filename));//根据文件明自动获取文件类型 response.setCharacterEncoding("UTF-8");//告知文件用什么服务器编码 PrintWriter pw=response.getWriter(); pw.write("Hello,world"); } /** * The doPost method of the servlet. <br> * * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } /** * Initialization of the servlet. <br> * * @throws ServletException if an error occurs */ public void init() throws ServletException { // Put your code here } }
首先指定一个需要下载的文件的文件名,然后告知浏览器需要下载文件,根据文件明自动获取文件类型,并告知文件用什么服务器编码。执行servlet后,会下载一个名为
a.csv的文件。
下载后,可以看到文件中存有Hello,world字符。