commons-fileUpload实现文件上传下载

目录

一、文件上传

二、文件下载


一、文件上传

(1).简介

    commons-fileUpload上传组件是Apache的一个开源项目,可以到http://commons.apache.org/proper/commons-fileupload/下载最新版本(该组件需要commons-io包的支持)。该组件使用方便,同样可以实现一个或多个文件的上传,也可实现限制上传文件大小等功能。

    在文件上传中,文件上传请求由有序的表单项列表组成,fileUpload能够解析上传请求,然后向应用提供一个文件表单项的列表。每个这样的表单项都实现了FileItem接口,用来封装单个表单字段元素的数据。

(2).使用要求

    1、使用commons-fileUpload组件上传文件时,需要将form表单的enctype属性设置为multipart/form-data;method属性设置为post

    2、将相应的commons-fileUpload包和commons-io包拷贝放入到你的web工程WEN-INF/lib目录下并Add to Build Path。

(3).使用步骤

①添加maven依赖(建议将jar包拷贝到WEN-INF/lib下)

<dependency>

    <groupId>commons-io</groupId>

    <artifactId>commons-io</artifactId>

    <version>2.6</version>

</dependency>

 

<dependency>

    <groupId>commons-fileupload</groupId>

    <artifactId>commons-fileupload</artifactId>

    <version>1.3.3</version>

</dependency>

②前端jsp页面

<form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">

    用户名:<input type="text" name="username"><br />

    文件:<input type="file" name="userfile"><br />

    <input type="submit" value="提交">

</form>

③后端servlet代码

package com.zzs.commons.upload;

 

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.PrintWriter;

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;

 

public class FileUploadTest extends HttpServlet {

 

    private String serverPath = null;

 

    @Override

    protected void doGet(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

       response.setHeader("Content-type", "text/html;charset=UTF-8");

       response.setCharacterEncoding("UTF-8");

 

       serverPath = getServletContext().getRealPath("/");

       System.out.println(serverPath);

 

       String savePath = serverPath + "/upload";

       String tmpPath = savePath + "/tmp";

 

       // Servlet初始化时执行,如果上传文件目录不存在则自动创建

       if (!new File(savePath).exists()) {

           new File(savePath).mkdirs();

       }

       if (!new File(tmpPath).exists()) {

           new File(tmpPath).mkdirs();

       }

 

       // 消息提示

       String message = "";

       try {

           // 使用Apache文件上传组件处理文件上传步骤:

           // 1、创建一个DiskFileItemFactory工厂

           DiskFileItemFactory factory = new DiskFileItemFactory();

           // 设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。

           factory.setSizeThreshold(1024 * 100);// 设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB

           // 设置上传时生成的临时文件的保存目录

           factory.setRepository(new File(tmpPath));

 

           // 2、创建一个文件上传解析器

           ServletFileUpload upload = new ServletFileUpload(factory);

           // 监听文件上传进度

           upload.setProgressListener(new ProgressListener() {

              public void update(long pBytesRead, long pContentLength, int arg2) {

                  System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead);

              }

           });

           // 解决上传文件名的中文乱码

           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 name = item.getFieldName();

                  // 得到上传的文件名称

                  String filename = item.getName();

                  System.out.println(name + "=" + filename);

 

                  if (filename == null || filename.trim().equals("")) {

                     continue;

                  }

 

                  // 注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.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 = UUID.randomUUID().toString() + "_" + filename;

                  // 得到文件的保存目录

                  String realSavePath = makePath(saveFilename, savePath);

 

                  // 创建一个文件输出流

                  FileOutputStream out = new FileOutputStream(realSavePath + "\\" + saveFilename);

 

                  byte buffer[] = new byte[1024];

                  int len = 0;

                  while ((len = in.read(buffer)) > 0) {

                     out.write(buffer, 0, len);

                  }

                  in.close();

                  out.close();

                  // 删除处理文件上传时生成的临时文件

                  // item.delete();

                  message = "文件上传成功!";

              }

           }

 

       // 这里的异常处理比较简单。开发中请根据实际要求改写

       } catch (FileUploadBase.FileSizeLimitExceededException e) {

           message = "单个文件超出最大值!!!";

           e.printStackTrace();

       } catch (FileUploadBase.SizeLimitExceededException e) {

           message = "上传文件的总的大小超出限制的最大值!!!";

           e.printStackTrace();

       } catch (Exception e) {

           message = "文件上传失败!";

           e.printStackTrace();

       }

 

       PrintWriter writer = response.getWriter();

       writer.write(message);

    }

 

    /**

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

     *

     * @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; // upload\2\3 upload\3\5

       // File既可以代表文件也可以代表目录

       File file = new File(dir);

       // 如果目录不存在

       if (!file.exists()) {

           // 创建目录

           file.mkdirs();

       }

       return dir;

    }

 

    @Override

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

       doGet(req, resp);

    }

}

 

④在web.xml中配置

<?xml version="1.0" encoding="UTF-8"?>

<web-app id="WebApp_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <servlet>

       <servlet-name>FileUpload</servlet-name>  

       <servlet-class>com.zzs.commons.upload.FileUploadTest</servlet-class>

    </servlet>

    <servlet-mapping>

       <servlet-name>FileUpload</servlet-name>  

       <url-pattern>/upload</url-pattern>

    </servlet-mapping>

   

    <welcome-file-list>

       <welcome-file>index.jsp</welcome-file>

    </welcome-file-list>

</web-app>

 

二、文件下载

文件下载比较简单,主要有两种方式:(1)直接通过超链接指向文件地址实现下载,(2)通过Servlet使用IO读写的方式。

这里介绍第二种方式:

①获取下载的文件列表

package com.zzs.commons.download;

 

import java.io.File;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

public class FileListTest extends HttpServlet {

    @Override

    protected void doGet(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

 

       // 获取资源目录

       String uploadFilePath = this.getServletContext().getRealPath("/WEB-INF/upload");

       // 存储要下载的文件名

       List<String> list = new ArrayList<>();

       // 递归遍历filepath目录下的所有文件和目录,将文件的文件名存储到list集合中

       listfile(new File(uploadFilePath), list);// File既可以代表一个文件也可以代表一个目录

 

       // list集合发送到页面进行显示

       request.setAttribute("fileNameList", list);

        request.getRequestDispatcher("/page/listfile.jsp").forward(request, response);

    }

 

    public void listfile(File file, List<String> list) {

       // 如果file代表的不是一个文件,而是一个目录

       if (!file.isFile()) {

           // 列出该目录下的所有文件和目录

           File files[] = file.listFiles();

           // 遍历files[]数组

           for (File f : files) {

              // 递归

              listfile(f, list);

           }

       } else {

           String realName = file.getName();

           list.add(realName);

       }

    }

 

    @Override

    protected void doPost(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

       doGet(request, response);

    }

}

 

展示下载文件列表的前端页面listfile.jsp

<table>

    <!-- 遍历List集合 -->

    <c:forEach var="list" items="${fileNameList }">

       <c:url value="/download" var="downurl">

           <c:param name="filename" value="${list }"></c:param>

       </c:url>

       <tr>

       <td>

               ${list }

           </td>

           <td>

               <a href="${downurl }">下载</a>

           </td>

       </tr>

    </c:forEach>

</table>

 

Web.xml配置该Servlet:

<servlet>

    <servlet-name>FileList</servlet-name>

    <servlet-class>com.zzs.commons.download.FileListTest</servlet-class>

</servlet>

<servlet-mapping>

    <servlet-name>FileList</servlet-name>

    <url-pattern>/list</url-pattern>

</servlet-mapping>

 

前台访问链接:http://localhost:8080/test/list

②获取下载文件

点击下载后会跳转到这个Servlet:

package com.zzs.commons.download;

 

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.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

public class FileDownloadTest extends HttpServlet {

 

    @Override

    protected void doGet(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

       // 得到要下载的文件名

       String fileName = request.getParameter("filename");

       System.out.println(fileName);

       fileName = new String(fileName.getBytes("iso8859-1"), "UTF-8");

 

       // 上传的文件都是保存在/WEB-INF/upload目录下的子目录当中

       String fileSaveRootPath = this.getServletContext().getRealPath("/WEB-INF/upload");

       // 得到要下载的文件

       File file = new File(fileSaveRootPath + "\\" + fileName);

       // 如果文件不存在

       if (!file.exists()) {

           request.setAttribute("message", "您要下载的资源已被删除!!");

           request.getRequestDispatcher("/page/message.jsp").forward(request, response);

           return;

       }

 

       // 设置响应头,控制浏览器下载该文件

       // 设置文件MIME类型

       response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

 

       FileInputStream in = new FileInputStream(file);

       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();

    }

 

    @Override

    protected void doPost(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

       doGet(request, response);

    }

}

 

在web.xml中配置该Servlet:

<servlet>

    <servlet-name>FileDownload</servlet-name>

    <servlet-class>com.zzs.commons.download.FileDownloadTest</servlet-class>

</servlet>

<servlet-mapping>

    <servlet-name>FileDownload</servlet-name>

    <url-pattern>/download</url-pattern>

</servlet-mapping>

 

 

参考文献:

JavaWeb学习总结(五十)——文件上传和下载

 https://www.cnblogs.com/xdp-gacl/p/4200090.html

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值