描述:关于文件上传下载的问题,我其实已经写了几篇关于不同情况,该如何进行处理了,这篇文章主要是针对在J2EE中如何利用方便的技能进行完成该功能,并且对里面的很多细节知识,进行了很详细的说明,请多多注意注释内容。如果需要的话,可以阅读一下另外的几篇文章来进行更加深入的学习。
文章一:http://blog.csdn.net/Cs_hnu_scw/article/details/78755519
文章二:http://blog.csdn.net/Cs_hnu_scw/article/details/77929869
一:文件上传
知识点1:单个文件上传处理
方法一:通过Apache的相关包
开发步骤:
(1)导包:
(2)JSP页面:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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>上传文件</title> </head> <body> <form action="${pageContext.request.contextPath}/uploadservlet" method="post" enctype="multipart/form-data"> 文件描述:<input type="text" name="description"> <input type="file" name="uploadfile"> <input type="submit" value="上传"> </form> </body> </html>
(3)servlet代码
package com.hnu.scw.upload.demo1; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List; import java.util.UUID; import javax.naming.SizeLimitExceededException; 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.FileSizeLimitExceededException; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.ProgressListener; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.IOUtils; import sun.security.jca.GetInstance.Instance; /** * 进行文件上传的demo1 * @author scw * */ public class UploadFileDemo1 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //解决文件乱码问题 request.setCharacterEncoding("utf-8"); //1:创建文件上传的工厂类实例对象 DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory(); //为了提高对于大文件上传的效率,这里就添加一个临时目录,放在WEB-INF下的tmp,当然放在WEB-INF目前外面也可以 diskFileItemFactory.setRepository(new File("WEB-INF/tmp")); diskFileItemFactory.setSizeThreshold(1024*1024*3); //2:创建文件上传的servletFileUpload实例对象 ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory); //解析request对象的内容 try { //设置文件上传的大小限制 servletFileUpload.setFileSizeMax(1024*1024*3); //单个文件不能超过3M servletFileUpload.setSizeMax(1024*1024*10); //总的上传文件大小不能超过10M //进行模拟进度条功能服务器端的实现 //(1)获取上传的时间 long startTime = System.currentTimeMillis(); //(2)实现进度条监听器 servletFileUpload.setProgressListener(new ProgressListener() { /** * 第一个参数:已经上传的大小 * 第二个参数:总的大小 * 第三个参数:上传标签中文件是第几个顺序,这个没什么作用 */ @Override public void update(long alreadloadsize, long totalsize, int formnumber) { //获取当前的时间 long currentTime = System.currentTimeMillis(); //计算已经花费的时间 long useTime = currentTime - startTime; //计算上传的速度 long speed = alreadloadsize / useTime ; //计算还剩于未上传的大小 long unloadsize = totalsize - alreadloadsize; //计算还需要上传的时间 long nextTime = unloadsize / speed ; System.out.println("已经花费时间:" + useTime); System.out.println("上传速度:" + speed ); System.out.println("剩余大小:" + unloadsize); System.out.println("剩余时间:" + nextTime); } }); List<FileItem> parseRequest = servletFileUpload.parseRequest(request); //4:遍历内容 for (FileItem fileItem : parseRequest) { //如果是true,则表示获取的当前内容数据是非上传文件内容,返回false就是上传文件的内容 if(fileItem.isFormField()){ //获取到JSP对应标签的name属性内容 String fieldName = fileItem.getFieldName(); //获取JSP对应标签value的内容,并且解决中文乱码问题 String value = fileItem.getString("utf-8"); System.out.println(fieldName + "@" + value); }else{ //获取到上传文件中,上传文件的名字 String name = fileItem.getName(); //为了解决一些浏览器(比如IE6)上传文件的时候,上传文件名是整个路径,比如C:\\upload\file\aa.txt所以要特别处理一下, //但是一般目前不存在这个问题了,主要针对一些老浏览器 int index = name.lastIndexOf("\\"); //如果匹配到的索引大于等于0,就表示需要进行截取,因为匹配不到的话是返回-1 if(index >= 0){ name = name.substring(index+1 , name.length()); } //为了防止,如果上传的文件名字一样,那么就会把之前的进行替换,所以这里也要特别处理一下(当然用时间戳也行) name = UUID.randomUUID().toString() + name; //获取到上传文件的字节流内容 InputStream inputStream = fileItem.getInputStream(); //获取存放上传内容的路径 //上传路径如果是想放在web-inf目录外就下面的形式 String realPath = getServletContext().getRealPath("/demo1path"); //如果想放在web-inf目录内部的话,就下面的形式,建议这样的方式,因为这样的话就不能直接从浏览器访问这个目录下面的内容,更加安全 //String realPath = getServletContext().getRealPath("WEB-INF/demo1path"); //创建出文件路径,防止目录不存在的时候出现异常问题 if(!new File(realPath).exists()){ new File(realPath).mkdirs(); } //创建输出流,这里用缓冲输出流,能够提高上传的效率 OutputStream os =new BufferedOutputStream( new FileOutputStream(new File(realPath , name))); //进行上传处理,用到commons.io.jar包里面的一个方法,相对比一般的处理方便点 IOUtils.copy(inputStream, os); //将临时目录中的内容进行删除,这也是由于之前为了提高上传效率而添加的临时目录 fileItem.delete(); //关闭资源 inputStream.close(); os.close(); } } } catch (Exception e) { //抓取单个文件上传大小超过限制 if(e instanceof FileSizeLimitExceededException){ System.out.println("单个文件太大啦~~~~~~~~~~~"); } //抓取上传多个文件上传大小超过限制 if(e instanceof SizeLimitExceededException){ System.out.println("总的上传文件太大啦~~~~~~~~~~~"); } e.printStackTrace(); } } }
(4)项目目录
知识点2:多个文件上传处理
JSP页面:(后台处理和上面的单个上传的是一样的,只是必须保证<input >属性的name必须一致)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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>动态多文件上传</title> </head> <script type="text/javascript"> //添加文件上传的框个数 function addFileItem() { document.getElementById("filediv").innerHTML +="<div><input type='file' name='uploadfile'><input type='button' onclick='deleteFileItem(this)' value='删除'></div>" } //删除文件上传的框个数 function deleteFileItem(currentbtn){ var divbtn = currentbtn.parentNode; divbtn.parentNode.removeChild(divbtn); } </script> <body> <form action="${pageContext.request.contextPath}/uploadservlet" method="post" enctype="multipart/form-data"> <input type="button" id ="addfile" onclick="addFileItem()" value="添加上传文件"> <div id="filediv"> </div> <input type="submit" value="上传"> </form> </body> </html>
方法二:通过servlet自带的方法
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>文件上传页面</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 action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data"> <input type="text" name="filetext"><br> <input type="file" name="upload"><br> <input type="submit" value="上传"> </form> </body> </html>
servlet代码:(通过注解来完成了配置)
package com.hnu.scw.upload.demo3; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; @WebServlet(urlPatterns={"/upload"}) @MultipartConfig( fileSizeThreshold=1024*1024*3, // 设置缓存大小 maxFileSize=1024*1024*3, // 设置上传单个文件大小 maxRequestSize=1024*1024*10 // 设置上传总大小 ) public class UploadFileDemo3 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 { // 如何来处理文件的上传逻辑:Part接口 request.setCharacterEncoding("utf-8"); /* * 1 如何获取文件上传的普通项? * * 通过Request对象的getParameter(String name)方法,可以或上传的普通项. * * name参数:指定客户端页面上传普通项的name属性值. */ String filetext = request.getParameter("filetext"); /* * 2 如何获取Part接口的实例对象? * * 通过Request对象的getPart(String name)方法,可以获取Part接口的实例对象. * * name参数:指定客户端页面上传文件域的name属性值. * * 通过Part接口的实例对象获取有关文件上传项的名称、文件输入流. * * Part接口提供的write(filename)方法: * * 将接收到的文件输入流,写入指定的服务器端的目录中. * * 参数filename:指定的保存文件的绝对路径. * * Part接口提供getName()方法: * * 获取的是上传文件域的name属性值. * * 并没有获取真实上传的文件名称. * * 上传的真实文件名称应该是如何获取到的呢? * * Servlet 3.0完成文件上传功能的诟病. * * */ Part part = request.getPart("upload"); /*String filename = part.getName(); System.out.println(filename);*/ /* * 获取上传的真实文件名称: * Content-Disposition: form-data; name="upload"; filename="readme.txt" */ String header = part.getHeader("Content-Disposition"); int index = header.lastIndexOf("filename=\""); String filename = header.substring(index+10, header.length()-1); InputStream in = part.getInputStream(); String realPath = getServletContext().getRealPath("/uploads"); part.write(realPath+"/"+filename); } }
二:文件下载
步骤:
(1)JSP(模拟需要下载的文件列表)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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>文件下载处理</title> </head> <body> <h1>下载内容列表如下所示:</h1> <a href="${pageContext.request.contextPath}/downfile?filename=1.et">下载1.et</a> <a href="${pageContext.request.contextPath}/downfile?filename=2.txt">下载2.txt</a> </body> </html>
(2)servlet代码
package com.hnu.scw.filedown.demo2; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; 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; import org.apache.catalina.util.Base64; import org.apache.commons.io.IOUtils; import sun.misc.BASE64Encoder; /** * 处理文件下载 * @author scw * */ public class FileDownDemo extends HttpServlet { /** * 因为在JSP这里是直接用a标签过来的,所以就在Get方法里面进行请求处理 */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1: 获取要下载的文件的名字 String fileName = request.getParameter("filename"); //为防止中文乱码造成的问题,所以要进行处理 fileName = new String(fileName.getBytes("ISO-8859-1"),"UTF-8"); //2:然后根据文件名,去数据库找对应存储的位置(这里就不进行数据库操作,就模拟一下) String downPath = ""; //假如要下载的文件名是2.txt,那么就去路径tomcat下对应工程的中路径找,我这里是放在downfilepath文件目录:找 if("2.txt".equals(fileName)){ downPath = "D:\\apache-tomcat-7.0.70\\webapps\\UploadFileServletProject\\downfilepath\\2.txt"; } //假如要下载的文件名是1.et,那么就去路径:找 else if("1.et".equals(fileName)){ downPath = "D:\\apache-tomcat-7.0.70\\webapps\\UploadFileServletProject\\downfilepath\\1.et"; } //-----------上面的路径实际开发中应该去去数据库进行寻找,上面只是模拟而已----------------- //3:获取输入流 FileInputStream io = new FileInputStream(new File(downPath)); //-----下面是解决当下载的文件名中有中文的时候,显示的时候如果不处理,会中文内容显示不出来-------- //主要是对IE和其他浏览器进行分别处理 String header = request.getHeader("User-Agent"); if(header.contains("MSIE")){ //表示是IE浏览器 fileName = URLEncoder.encode(fileName); fileName = fileName.replace("+", " "); }else{ //是其他类型的浏览器 BASE64Encoder base64Encoder = new BASE64Encoder(); //这是固定的处理方式 fileName = "=?utf-8?B?" + base64Encoder.encode(fileName.getBytes("utf-8")) + "?="; } //-------处理结束----------------------- //4:设置告诉浏览器要以文件下载的方式进行下载(如果不指定的话,那么浏览器不会以下载的方式进行,所以就存在问题) response.setContentType(getServletContext().getMimeType(fileName)); response.setHeader("Content-Disposition", "attachment;filename="+fileName); //5:获取输入流 OutputStream os = response.getOutputStream(); //6:进行下载处理 IOUtils.copy(io, os); //7:关闭资源 io.close(); os.close(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }整合文件上传和下载的项目结构如下所示:
慢慢的一步步分析下来的话,其实对于文件处理,并不是很复制,流程逻辑还是很清晰的,另外的话,对于不同其他情况的处理,欢迎查看其他上述提到的文章哦~!~!