zoukankan      html  css  js  c++  java
  • javaWeb中的文件上传下载

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现。

      对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件。这个common-fileupload上传组件的jar包可以去apache官网上面下载,也可以在struts的lib文件夹下面找到,struts上传的功能就是基于这个实现的。common-fileupload是依赖于common-io这个包的,所以还需要下载这个包,也可以直接去maven库中搜索这个包。如果使用servlet3.0的话就不需要下载包了,直接支持文件上传。

    apache官网也有servlet部分的代码演示和讲解,地址:http://commons.apache.org/proper/commons-fileupload/

    环境目录:

    index.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>Insert title here</title>
    </head>
    <body>
    <a href="upload.jsp">上传</a><br>
    <a href="/downLoad">下载</a>
    </body>
    </html>
    

    upload.jsp代码

    <%@ page language="java" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML>
    <html>
      <head>
        <title>Servlet3.0实现文件上传</title>
      </head>
      
      <body>
            <fieldset>
                <legend>
                    上传单个文件
                </legend>
            //${pageContext.request.contextPath}保证部署后路径正确 <!-- 文件上传时必须要设置表单的enctype="multipart/form-data"--> <form action="${pageContext.request.contextPath}/UploadServlet" method="post" enctype="multipart/form-data"> 上传文件: <input type="file" name="file"> <br> <input type="submit" value="上传"> </form> </fieldset> <hr /> <fieldset> <legend> 上传多个文件 </legend> <!-- 文件上传时必须要设置表单的enctype="multipart/form-data"--> <form action="${pageContext.request.contextPath}/UploadServlet" method="post" enctype="multipart/form-data"> 上传文件: <input type="file" name="file1"> <br> 上传文件: <input type="file" name="file2"> <br> <input type="submit" value="上传"> </form> </fieldset> </body> </html>

    开发处理文件上传的Servlet

      1、使用注解@MultipartConfig将一个Servlet标识为支持文件上传。

      2、Servlet3.0将multipart/form-data的POST请求封装成Part,通过Part对上传的文件进行操作

     

    package servlet;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    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 org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    
    //使用@WebServlet配置UploadServlet的访问路径
    @WebServlet(name="UploadServlet",urlPatterns="/UploadServlet")
    //使用注解@MultipartConfig将一个Servlet标识为支持文件上传
    @MultipartConfig//标识Servlet支持文件上传
    public class UploadServlet extends HttpServlet {
    
        /**
    	 * 
    	 */
    	private static final long serialVersionUID = 1L;
    
    	public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
                    //得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
                    String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
                    File file = new File(savePath);
                    //判断上传文件的保存目录是否存在
                    if (!file.exists() && !file.isDirectory()) {
                        System.out.println(savePath+"目录不存在,需要创建");
                        //创建目录
                        file.mkdir();
                    }
                    //消息提示
                    String message = "";
                    try{
                        //使用Apache文件上传组件处理文件上传步骤:
                        //1、创建一个DiskFileItemFactory工厂
                        DiskFileItemFactory factory = new DiskFileItemFactory();
                        //2、创建一个文件上传解析器
                        ServletFileUpload upload = new ServletFileUpload(factory);
                         //解决上传文件名的中文乱码
                        upload.setHeaderEncoding("UTF-8"); 
                        //3、判断提交上来的数据是否是上传表单的数据
                        if(!ServletFileUpload.isMultipartContent(request)){
                            //按照传统方式获取数据
                            return;
                        }
                        //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
                        List<FileItem> list = upload.parseRequest(request);
                        for(FileItem item : list){
                            //如果fileitem中封装的是普通输入项的数据
                            if(item.isFormField()){
                                String name = item.getFieldName();
                                //解决普通输入项的数据的中文乱码问题
                                String value = item.getString("UTF-8");
                                //value = new String(value.getBytes("iso8859-1"),"UTF-8");
                                System.out.println(name + "=" + value);
                            }else{//如果fileitem中封装的是上传文件
                                //得到上传的文件名称,
                                String filename = item.getName();
                                System.out.println(filename);
                                if(filename==null || filename.trim().equals("")){
                                    continue;
                                }
                                //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:a1.txt,而有些只是单纯的文件名,如:1.txt
                                //处理获取到的上传文件的文件名的路径部分,只保留文件名部分
                                filename = filename.substring(filename.lastIndexOf("\")+1);
                                //获取item中的上传文件的输入流
                                InputStream in = item.getInputStream();
                                //创建一个文件输出流
                                FileOutputStream out = new FileOutputStream(savePath + "\" + filename);
                                //创建一个缓冲区
                                byte buffer[] = new byte[1024];
                                //判断输入流中的数据是否已经读完的标识
                                int len = 0;
                                //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
                                while((len=in.read(buffer))>0){
                                    //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\" + filename)当中
                                    out.write(buffer, 0, len);
                                }
                                //关闭输入流
                                in.close();
                                //关闭输出流
                                out.close();
                                //删除处理文件上传时生成的临时文件
                                item.delete();
                                message = "文件上传成功!";
                            }
                        }
                    }catch (Exception e) {
                        message= "文件上传失败!";
                        e.printStackTrace();
                        
                    }
                    request.setAttribute("message",message);
                    request.getRequestDispatcher("/message.jsp").forward(request, response);
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            doGet(request, response);
        }
    }
    

     上传成功后meaasge.jsp

    <%@ page language="java" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML>
    <html>
      <head>
        <title>消息提示</title>
      </head>
      
      <body>
            ${message}
      </body>
    </html>
    

     web.xml配置

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:web="http://xmlns.jcp.org/xml/ns/javaee" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd http://xmlns.jcp.org/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.4"> <display-name>Spring MVC Application</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>

    文件上传的细节

      上述的代码虽然可以成功将文件上传到服务器上面的指定目录当中,但是文件上传功能有许多需要注意的小细节问题,以下列出的几点需要特别注意的

      1、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。

      2、为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。

      3、为防止一个目录下面出现太多文件,要使用hash算法打散存储。

      4、要限制上传文件的最大值。

      5、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。

      针对上述提出的5点细节问题,我们来改进一下UploadHandleServlet,改进后的代码如下:

    package servlet;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    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.ProgressListener;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    
    //使用@WebServlet配置UploadServlet的访问路径
    @WebServlet(name="UploadServlet",urlPatterns="/UploadServlet")
    //使用注解@MultipartConfig将一个Servlet标识为支持文件上传
    @MultipartConfig//标识Servlet支持文件上传 public class UploadServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全 String savePath = this.getServletContext().getRealPath("/WEB-INF/upload"); //上传时生成的临时文件保存目录 String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp"); File tmpFile = new File(tempPath); if (!tmpFile.exists()) { //创建临时目录 tmpFile.mkdir(); } //消息提示 String message = ""; try{ //使用Apache文件上传组件处理文件上传步骤: //1、创建一个DiskFileItemFactory工厂 DiskFileItemFactory factory = new DiskFileItemFactory(); //设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。 factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB //设置上传时生成的临时文件的保存目录 factory.setRepository(tmpFile); //2、创建一个文件上传解析器 ServletFileUpload upload = new ServletFileUpload(factory); //监听文件上传进度 upload.setProgressListener(new ProgressListener(){ public void update(long pBytesRead, long pContentLength, int arg2) { System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead); /** * 文件大小为:14608,当前已处理:4096 文件大小为:14608,当前已处理:7367 文件大小为:14608,当前已处理:11419 文件大小为:14608,当前已处理:14608 */ } }); //解决上传文件名的中文乱码 upload.setHeaderEncoding("UTF-8"); //3、判断提交上来的数据是否是上传表单的数据 if(!ServletFileUpload.isMultipartContent(request)){ //按照传统方式获取数据 return; } //设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB upload.setFileSizeMax(1024*1024); //设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB upload.setSizeMax(1024*1024*10); //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项 List<FileItem> list = upload.parseRequest(request); for(FileItem item : list){ //如果fileitem中封装的是普通输入项的数据 if(item.isFormField()){ String name = item.getFieldName(); //解决普通输入项的数据的中文乱码问题 String value = item.getString("UTF-8"); //value = new String(value.getBytes("iso8859-1"),"UTF-8"); System.out.println(name + "=" + value); }else{//如果fileitem中封装的是上传文件 //得到上传的文件名称, String filename = item.getName(); System.out.println(filename); if(filename==null || filename.trim().equals("")){ continue; } //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:a1.txt,而有些只是单纯的文件名,如:1.txt //处理获取到的上传文件的文件名的路径部分,只保留文件名部分 filename = filename.substring(filename.lastIndexOf("\")+1); //得到上传文件的扩展名 String fileExtName = filename.substring(filename.lastIndexOf(".")+1); //如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法 System.out.println("上传的文件的扩展名是:"+fileExtName); //获取item中的上传文件的输入流 InputStream in = item.getInputStream(); //得到文件保存的名称 String saveFilename = makeFileName(filename); //得到文件的保存目录 String realSavePath = makePath(saveFilename, savePath); //创建一个文件输出流 FileOutputStream out = new FileOutputStream(realSavePath + "\" + saveFilename); //创建一个缓冲区 byte buffer[] = new byte[1024]; //判断输入流中的数据是否已经读完的标识 int len = 0; //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据 while((len=in.read(buffer))>0){ //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\" + filename)当中 out.write(buffer, 0, len); } //关闭输入流 in.close(); //关闭输出流 out.close(); //删除处理文件上传时生成的临时文件 //item.delete(); message = "文件上传成功!"; } } }catch (FileUploadBase.FileSizeLimitExceededException e) { e.printStackTrace(); request.setAttribute("message", "单个文件超出最大值!!!"); request.getRequestDispatcher("/message.jsp").forward(request, response); return; }catch (FileUploadBase.SizeLimitExceededException e) { e.printStackTrace(); request.setAttribute("message", "上传文件的总的大小超出限制的最大值!!!"); request.getRequestDispatcher("/message.jsp").forward(request, response); return; }catch (Exception e) { message= "文件上传失败!"; e.printStackTrace(); } request.setAttribute("message",message); request.getRequestDispatcher("/message.jsp").forward(request, response); } /** * @Method: makeFileName * @Description: 生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称 * @param filename 文件的原始名称 * @return uuid+"_"+文件的原始名称 */ private String makeFileName(String filename){ //2.jpg //为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名 return UUID.randomUUID().toString() + "_" + filename; } /** * 为防止一个目录下面出现太多文件,要使用hash算法打散存储 * @Method: makePath * @Description: * * @param filename 文件名,要根据文件名生成存储目录 * @param savePath 文件存储路径 * @return 新的存储目录 */ private String makePath(String filename,String savePath){ //得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址 int hashcode = filename.hashCode(); int dir1 = hashcode&0xf; //0--15 int dir2 = (hashcode&0xf0)>>4; //0-15 //构造新的保存目录 String dir = savePath + "\" + dir1 + "\" + dir2; //upload23 upload35 //File既可以代表文件也可以代表目录 File file = new File(dir); //如果目录不存在 if(!file.exists()){ //创建目录 file.mkdirs(); } return dir; } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }

     

    使用Servlet3.0上传文件

    package servlet;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Collection;
    
    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配置UploadServlet的访问路径
    @WebServlet(name = "FileUploadServlet", urlPatterns = "/FileUploadServlet")
    // 使用注解@MultipartConfig将一个Servlet标识为支持文件上传
    @MultipartConfig // 标识Servlet支持文件上传
    public class FileUploadServlet extends HttpServlet {
    
    	public void doGet(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		request.setCharacterEncoding("utf-8");
    		response.setCharacterEncoding("utf-8");
    		response.setContentType("text/html;charset=utf-8");
    		// 存储路径
    		String savePath = "D:\";
    		// 获取上传的文件集合
    		Collection<Part> parts = request.getParts();
    		// 上传单个文件
    		if (parts.size() == 1) {
    			// Servlet3.0将multipart/form-data的POST请求封装成Part,通过Part对上传的文件进行操作。
    			// Part part = parts[0];//从上传的文件集合中获取Part对象
    			Part part = request.getPart("file");// 通过表单file控件(<input type="file"
    												// name="file">)的名字直接获取Part对象
    			// Servlet3没有提供直接获取文件名的方法,需要从请求头中解析出来
    			// 获取请求头,请求头的格式:form-data; name="file"; filename="snmp4j--api.zip"
    			String header = part.getHeader("content-disposition");
    			// 获取文件名
    			String fileName = getFileName(header);
    			// 把文件写到指定路径
    			part.write(savePath + File.separator + fileName);
    		} else {
    			// 一次性上传多个文件
    			for (Part part : parts) {// 循环处理上传的文件
    				// 获取请求头,请求头的格式:form-data; name="file";
    				// filename="snmp4j--api.zip"
    				String header = part.getHeader("content-disposition");
    				// 获取文件名
    				String fileName = getFileName(header);
    				// 把文件写到指定路径
    				part.write(savePath + File.separator + fileName);
    			}
    		}
    		PrintWriter out = response.getWriter();
    		out.println("上传成功");
    		out.flush();
    		out.close();
    	}
    
    	/**
    	 * 根据请求头解析出文件名 请求头的格式:火狐和google浏览器下:form-data; name="file";
    	 * filename="snmp4j--api.zip" IE浏览器下:form-data; name="file";
    	 * filename="E:snmp4j--api.zip"
    	 * 
    	 * @param header
    	 *            请求头
    	 * @return 文件名
    	 */
    	public String getFileName(String header) {
    		/**
    		 * String[] tempArr1 =
    		 * header.split(";");代码执行完之后,在不同的浏览器下,tempArr1数组里面的内容稍有区别
    		 * 火狐或者google浏览器下:tempArr1={form-data,name="file",filename=
    		 * "snmp4j--api.zip"}
    		 * IE浏览器下:tempArr1={form-data,name="file",filename="E:snmp4j--api.zip"}
    		 */
    		String[] tempArr1 = header.split(";");
    		/**
    		 * 火狐或者google浏览器下:tempArr2={filename,"snmp4j--api.zip"}
    		 * IE浏览器下:tempArr2={filename,"E:snmp4j--api.zip"}
    		 */
    		String[] tempArr2 = tempArr1[2].split("=");
    		// 获取文件名,兼容各种浏览器的写法
    		String fileName = tempArr2[1]
    				.substring(tempArr2[1].lastIndexOf("\") + 1)
    				.replaceAll(""", "");
    		return fileName;
    	}
    
    	public void doPost(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		this.doGet(request, response);
    	}
    }
    

    点击下载要从web-inf下找到目录文件并且列出到download.jsp中

    ListFileServlet

    package servlet;
    
    
    import java.io.File;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
    * @ClassName: ListFileServlet
    * @Description: 列出Web系统中所有下载文件
    * @date: 2015-1-4 下午9:54:40
    *
    */ 
    @WebServlet(name="ListFileServlet",urlPatterns="/download")
    public class ListFileServlet  extends HttpServlet{
        /**
    	 * 
    	 */
    	private static final long serialVersionUID = 1L;
    
    	public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            //获取上传文件的目录
            String uploadFilePath = this.getServletContext().getRealPath("/WEB-INF/upload");
            //存储要下载的文件名
            Map<String,String> fileNameMap = new HashMap<String,String>();
            //递归遍历filepath目录下的所有文件和目录,将文件的文件名存储到map集合中
            listfile(new File(uploadFilePath),fileNameMap);//File既可以代表一个文件也可以代表一个目录
            //将Map集合发送到listfile.jsp页面进行显示
            request.setAttribute("fileNameMap", fileNameMap);
            request.getRequestDispatcher("/download.jsp").forward(request, response);
        }
        
        /**
        * @Method: listfile
        * @Description: 递归遍历指定目录下的所有文件
        * @param file 即代表一个文件,也代表一个文件目录
        * @param map 存储文件名的Map集合
        */ 
        public void listfile(File file,Map<String,String> map){
            //如果file代表的不是一个文件,而是一个目录
            if(!file.isFile()){
                //列出该目录下的所有文件和目录
                File files[] = file.listFiles();
                //遍历files[]数组
                for(File f : files){
                    //递归
                    listfile(f,map);
                }
            }else{
                /**
                 * 处理文件名,上传后的文件是以uuid_文件名的形式去重新命名的,去除文件名的uuid_部分
                    file.getName().indexOf("_")检索字符串中第一次出现"_"字符的位置,如果文件名类似于:9349249849-88343-8344_阿_凡_达.avi
                    那么file.getName().substring(file.getName().indexOf("_")+1)处理之后就可以得到阿_凡_达.avi部分
                 */
                String realName = file.getName().substring(file.getName().indexOf("_")+1);
                //file.getName()得到的是文件的原始名称,这个名称是唯一的,因此可以作为key,realName是处理过后的名称,有可能会重复
                map.put(file.getName(), realName);
            }
        }
        
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            this.doGet(request, response);
        }
    
    }
    

     download.jsp

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <!DOCTYPE HTML>
    <html>
      <head>
        <title>下载文件显示页面</title>
      </head>
      
      <body>
          <!-- 遍历Map集合 -->
        <c:forEach var="me" items="${fileNameMap}">
            <c:url value="/DownLoadServlet" var="downurl">
                <c:param name="filename" value="${me.key}"></c:param>
            </c:url>
            ${me.value}<a href="${downurl}">下载</a>
            <br/>
        </c:forEach>
      </body>
    </html>
    

     点击下载处理Servlet

    package servlet;
    
    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.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    @WebServlet(name = "DownLoadServlet", urlPatterns = "/DownLoadServlet")
    public class DownLoadServlet extends HttpServlet {
    
    	public void doGet(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		// 得到要下载的文件名
    		String fileName = request.getParameter("filename"); // 23239283-92489-阿凡达.avi
    		fileName = new String(fileName.getBytes("iso8859-1"), "UTF-8");
    		// 上传的文件都是保存在/WEB-INF/upload目录下的子目录当中
    		String fileSaveRootPath = this.getServletContext()
    				.getRealPath("/WEB-INF/upload");
    		// 通过文件名找出文件的所在目录
    		String path = findFileSavePathByFileName(fileName, fileSaveRootPath);
    		// 得到要下载的文件
    		File file = new File(path + "\" + fileName);
    		// 如果文件不存在
    		if (!file.exists()) {
    			request.setAttribute("message", "您要下载的资源已被删除!!");
    			request.getRequestDispatcher("/message.jsp").forward(request,
    					response);
    			return;
    		}
    		// 处理文件名
    		String realname = fileName.substring(fileName.indexOf("_") + 1);
    		// 设置响应头,控制浏览器下载该文件
    		response.setHeader("content-disposition",
    				"attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
    		// 读取要下载的文件,保存到文件输入流
    		FileInputStream in = new FileInputStream(path + "\" + fileName);
    		// 创建输出流
    		OutputStream out = response.getOutputStream();
    		// 创建缓冲区
    		byte buffer[] = new byte[1024];
    		int len = 0;
    		// 循环将输入流中的内容读取到缓冲区当中
    		while ((len = in.read(buffer)) > 0) {
    			// 输出缓冲区的内容到浏览器,实现文件下载
    			out.write(buffer, 0, len);
    		}
    		// 关闭文件输入流
    		in.close();
    		// 关闭输出流
    		out.close();
    	}
    
    	/**
    	 * @Method: findFileSavePathByFileName
    	 * @Description: 通过文件名和存储上传文件根目录找出要下载的文件的所在路径
    	 * @param filename
    	 *            要下载的文件名
    	 * @param saveRootPath
    	 *            上传文件保存的根目录,也就是/WEB-INF/upload目录
    	 * @return 要下载的文件的存储目录
    	 */
    	public String findFileSavePathByFileName(String filename,
    			String saveRootPath) {
    		int hashcode = filename.hashCode();
    		int dir1 = hashcode & 0xf; // 0--15
    		int dir2 = (hashcode & 0xf0) >> 4; // 0-15
    		String dir = saveRootPath + "\" + dir1 + "\" + dir2; // upload23
    								      // upload35
    		File file = new File(dir);
    		if (!file.exists()) {
    			// 创建目录
    			file.mkdirs();
    		}
    		return dir;
    	}
    
    	public void doPost(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		doGet(request, response);
    	}
    }
    

    使用JSPSmartUpload文件上传(未进行优化,使用场景是提交除了上传文件,还有其他值)

    package servlet;
    
    import java.io.IOException;
    
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import service.GoodsService;
    import service.impl.GoodsServiceImpl;
    
    import com.jspsmart.upload.SmartUpload;
    
    import entity.Goods;
    
    /**
     * 增加商品 2015-3-6
     */
    @WebServlet(urlPatterns = "/addGoods")
    public class GoodsAddGoodsServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
    	GoodsService service = new GoodsServiceImpl();
    	Goods goods = new Goods();
    
    	public GoodsAddGoodsServlet() {
    		super();
    	}
    
    	@Override
    	public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
    		// 初始化下载对象
    		SmartUpload su = new SmartUpload();
    		try {
    			// 初始化上传对象
    			su.initialize(getServletConfig(), request, response);
    			// 设置单文件最大容量
    			su.setMaxFileSize(10 * 1024 * 1024);
    			// 设置所有文件最大容量
    			su.setTotalMaxFileSize(100 * 1024 * 1024);
    			// 设置上传文件类型
    			su.setAllowedFilesList("jpg,bmp,gif,png");
    			// 设置禁止上传的文件类型
    			su.setDeniedFilesList("jsp,js,html,css,rar,txt");
    			// 上传文件
    			su.upload();
    			// 获取单个上传文件
    			com.jspsmart.upload.File tempFile = null;
    			//多文件上传
    			/*for( int i=0; i<su.getFiles().getCount(); i++ ){
          			File file = su.getFiles().getFile(i);
          		}*/
    			tempFile = su.getFiles().getFile(0);
    			// 文件路径
    			String filePath = null;
    			// 文件名(需插入到数据库中作为字段内容)
    			String fileReName = null;
    			if (!tempFile.isMissing()) {
    				// 获取文件的长度
    				long SlaveSize = tempFile.getSize();
    				// 文件重命名
    				fileReName = System.currentTimeMillis() + SlaveSize + "." + tempFile.getFileExt();
    				filePath = "upload\";
    				filePath += fileReName;
    				// 保存文件
    				tempFile.saveAs(filePath, SmartUpload.SAVE_VIRTUAL);
    			}
    			System.out.println("fileName:" + fileReName);
    			System.out.println("-------------------------------------------------");
    			System.out.println("表单项名称:" + tempFile.getFieldName());// 取HTML表单中对应于此上传文件的表单项的名字
    			System.out.println("文件名:" + tempFile.getFileName());// 获取文件名(不包含路径)
    			System.out.println("文件长度:" + tempFile.getSize());// 获取文件的长度(以字节记)
    			System.out.println("文件扩展名:" + tempFile.getFileExt());// 获取文件扩展名
    			System.out.println("文件全名:" + tempFile.getFilePathName());// 取文件全名(带目录)
    			System.out.println("-------------------------------------------------");
    			String goods_name = su.getRequest().getParameter("goods_name");
    			int goods_num = Integer.parseInt(su.getRequest().getParameter("goods_num"));
    			float goods_price = Float.parseFloat(su.getRequest().getParameter("goods_price"));
    			int category_id = Integer.parseInt(su.getRequest().getParameter("category"));
    			String goods_desc = su.getRequest().getParameter("goods_desc");
    			System.out.println("goods_desc:"+goods_desc);
    			goods.setGoods_name(goods_name);
    			goods.setGoods_num(goods_num);
    			goods.setGoods_price(goods_price);
    			goods.setCategory_id(category_id);
    			goods.setGoods_desc(goods_desc);
    			goods.setGoods_image(fileReName);
    			service.addGoods(goods);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		response.sendRedirect("queryAllGoods");
    	}
    
    	@Override
    	public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
    		this.doGet(request, response);
    	}
    }
    

     注意:上面这种方式由于放在临时目录中,每次重启tomcat上传的文件会自动消失,可以在上传至服务器目录时再上传备份一个至硬盘中,如String savePath = "D:\";

    Appache Commons Upload文件上传

    http://cqjava.iteye.com/blog/2048233

     

  • 相关阅读:
    G
    O
    M
    K-Hero
    J
    G
    F
    Codeforces Round #327 (Div. 2) A Wizards' Duel (水题)
    C++各大有名科学计算库(转)
    矩阵算法 高斯消元 行列式 矩阵的秩
  • 原文地址:https://www.cnblogs.com/JAYIT/p/5028524.html
Copyright © 2011-2022 走看看