JavaWeb中实现文件上传和下载

一、文件上传

1.使用的组件
  使用DiskFileItemFactory、ServletFileUpload、FileItem三个组件实现。依赖的jar包为commons-fileupload-1.4.jarcommons-io-2.7.jar,下载地址:
https://download.csdn.net/download/Albert201605/26346276

——调用方法的说明
DiskFileItemFactory——解析器工厂,用于创建对请求内容的解析器
(1) public void setSizeThreshold(int sizeThreshold)
  设置内存缓冲区的大小,默认值为10K。当上传的文件大于缓冲区的大小时,fileupload组件将使用临时文件缓存上传的文件。

(2) public void setRepository(Java.io.File repository)
  指定临时文件目录,默认值为System.getProperty(“java.io.tmpdir”).

(3) public DiskFileItemFactory(int sizeThreshold,java.io.File repository)
  构造函数,同时赋以缓冲区大小和临时文件目录


ServletFileUpload——解析器,用以解析请求体的内容
(1)boolean isMultipartContent(HttpServletRequest request)
  判断上传表单是否为multipart/form-data类型

(2) List parseRequest(HttpServletRequest request)
  解析request对象,并把表单中的每一个输入项封装成一个FileItem 对象,返回一个保存了所有FileItem的List集合。

(3) setFileSizeMax(long fileSizeMax)
  设置上传文件的最大值(单个文件),用于设置单个上传文件的最大尺寸限制,以防止客户端恶意上传超大文件来浪费服务器端的存储空间。其参数是以字节为单位的long型数字。

(4) setSizeMax(long sizeMax) :
  设置整个请求消息实体内容(整个表单数据)的最大尺寸限制,以防止客户端恶意上传超大文件来浪费服务器端的存储空间。其参数是以字节为单位的long型数字。

(5) setHeaderEncoding(java.lang.String encoding)
  设置编码格式。在文件上传请求的消息体中,除了普通表单域的值是文本内容以外,文件上传字段中的文件路径名也是文本,在内存中保存的是它们的某种字符集编码的字节数组,Apache文件上传组件在读取这些内容时,必须指定所采用的字符集编码方式,才能将它们转换成正确的字符文本返回。


FileItem——条目对象,用以保存封装的表单字段
(1) boolean isFormField()
  isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单字段,还是一个文件表单字段,如果是普通表单字段返回true,否则返回false。

(2) String getName()
  用于获得文件上传字段中的文件名。注意IE或FireFox中获取的值是不一样的,IE中获取的是绝对路径,FireFox中获取的仅是文件名。

(3) String getFieldName()
  用于返回表单标签的name名。

(4) void write(File file)
  用于将FileItem对象中保存的主体内容写入到某个指定的文件中。如果FileItem对象中的主体内容是保存在某个临时文件中的,在该方法顺利完成后,临时文件有可能会被清除。使用该方法也可将普通表单字段内容写入到一个文件中,但它的主要用途仍是将上传的文件内容保存至本地文件系统中。

(5) String getString()
  用于将FileItem对象中保存的数据流内容以一个字符串返回,它有两个重载的定义形式:
public Java.lang.String getString();
public java.lang.String getString(java.lang.String encoding) throws java.io.UnsupportedEncodingException
  前者使用缺省的字符集编码将主体内容转换成字符串,后者使用参数指定了字符集编码将主体内容转换成字符串。如果在读取普通表单字段元素的内容时出现了中文乱码现象,则可调用第二个getString方法,指定正确的字符集编码格式。

(6) void delete()
  delete方法用于清空FileItem对象中存放的主体内容,如果主体内容被保存在了临时文件中,那么delete方法将删除该临时文件。值得注意的是,尽管当FileItem对象被垃圾收集器收集时会自动地清除临时文件,但及时调用delete方法可以更早地清除冗余的临时文件,有效释放系统的存储资源。


2.实现步骤
  s1.创建解析器工厂;
  s2.创建Servlet解析器;
  s3.解析请求,将表单的每个输入项封装为一个FileItem对象;
  s4.逐个处理item条目。对文件字段:创建文件 -> item内容写入。

**注:**在前端JSP页面中,须使用form表单,同时 (1)method须设置为post;
(2)须设置enctype=”multipart/form-data”,作用是将表单数据用以标签为单元、用分隔符分开的形式构造请求体。


二、文件下载

通过输入/输出流完成。
实现步骤:
  s1.将指定的文件生成输入流;
  s2.获取响应输出流;
  s3.将流对拷。


三、实现Demo

  IDEA开发,一个jsp页面,一个上传Servlet,一个下载Servlet。

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>Demo of File Upload and Download</title>
  </head>
  <body>
  <form action="/UploadServlet" method="post" enctype="multipart/form-data">
    <input type="text" name="my_comment" value="备注信息"/>
    <input type="file" name="my_file"/>
    <input type="submit" value="上传"/>
  </form>

  <%
    String download_file_name = "你好123abcdef.txt";
  %>
  <a href="/DownloadServlet?filename=<%=download_file_name%>">下载文件</a>
  </body>
</html>

UploadServlet.java

@WebServlet("/UploadServlet")
public class UploadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");

        /** 1.创建解析器工厂 */
        DiskFileItemFactory factory = new DiskFileItemFactory();

        //设置工厂内存缓存区大小,若未设定,则默认为10k
        factory.setSizeThreshold(1024*1024); //1M,参数是以字节为单位的int值。

        //设置工厂的临时文件目录
        File temp_file = new File("D:\\TempFolder");
        if (!temp_file.exists()){
            temp_file.mkdirs();
        }
        factory.setRepository(temp_file);

        /** 2.创建Servlet解析器 */
        ServletFileUpload servletFileUpload = new ServletFileUpload(factory);

        //设置上传数据的规模限制
        servletFileUpload.setSizeMax(1024*1024); //全体数据的最大尺寸限制(参数是以字节为单位的long值,这里是1M)
        servletFileUpload.setFileSizeMax(1024*1024); //单个文件的最大尺寸限制(参数是以字节为单位的long值,这里是1M)

        //设置字符编码格式
        servletFileUpload.setHeaderEncoding("UTF-8");

        try {
            /** 3.解析请求,将表单的每个输入项封装为一个FileItem对象 */
            List<FileItem> itemList = servletFileUpload.parseRequest(request);

            /** 4.逐个条目处理*/
            for (FileItem item : itemList) {
                if (item.isFormField()){ //普通字段
                    String field_name = item.getFieldName(); //获得字段的name名
                    String field_value = item.getString("UTF-8"); //获得字段的值
                    System.out.println("field_name:"+field_name);
                    System.out.println("field_value:"+field_value);
                }else { //文件字段
                    String field_name = item.getFieldName(); //获得字段的name名
                    String file_name = item.getName(); //获得上传文件的文件名称(对IE和FireFox,获取的值不同,对IE获取的是绝对路径,对FireFox获取的是文件名)
                    System.out.println("上传的文件名称:"+file_name);

                    //将item的内容存至磁盘文件
                    String upload_path = "D:\\myUploadedFile\\" + file_name;
                    File file = new File(upload_path); //定义文件对象
                    if (!file.exists()){ //若文件不存在,则创建
                        file.getParentFile().mkdirs();
                        file.createNewFile();
                    }

                    //方式一:以IO流的形式写入
                    InputStream inputStream = item.getInputStream(); //以输入流的形式获取item内容
                    FileOutputStream fileOutputStream = new FileOutputStream(file); //定义文件输出流,指定输出至文件对象
                    //将流对拷
                    byte[] bytes = new byte[1024]; //每次读取一个字节
                    int len;
                    while ((len=inputStream.read(bytes))>0) //读取输入流,写入输出流
                        fileOutputStream.write(bytes,0,len);

                    /*
                    //方式二:将item主体内容直接写入
                    //注:如果FileItem对象中的主体内容是保存在某个临时文件中,该方法顺利完成后,临时文件有可能会被清除
                    item.write(file);
                    */

                    inputStream.close();
                    fileOutputStream.close();
                    item.delete(); //释放item占用的存储资源

                    //向前端发出提示,重定向回主页面
                    PrintWriter printWriter=response.getWriter();
                    printWriter.print("<script>alert('上传成功!');window.location='"+request.getContextPath()+"/';</script>");

                }
            }

        }catch (Exception e){
            e.printStackTrace();
        }

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

DownloadServlet.java

@WebServlet("/DownloadServlet")
public class DownloadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String filename = request.getParameter("filename"); //获取前端传来的参数

        response.setContentType("text/html;charset=utf-8"); //通知客户端内容类型
        response.addHeader("Content-Type","application/octet-stream");
        response.addHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(filename, "UTF-8")); //通知浏览器以下载的方式打开,并对文件名进行编码

        //1.将指定的文件生成输入流
        String download_path = "D:\\myUploadedFile\\" + filename;
        File file = new File(download_path); //定义文件对象
        InputStream inputStream = new FileInputStream(file); //将文件对象生成为输入流

        //2.获取响应输出流
        OutputStream outputStream = response.getOutputStream();

        //3.将流对拷
        byte[] bytes = new byte[1024]; //每次读取一个字节
        int len;
        while ((len=inputStream.read(bytes))>0) //读取输入流,写入输出流
            outputStream.write(bytes,0,len);

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}


在这里插入图片描述

Demo工程文件打包下载:
https://download.csdn.net/download/Albert201605/26347671

End.


参考

  1. https://blog.csdn.net/u014785687/article/details/73863964
  2. https://www.cnblogs.com/w-wfy/p/6239330.html
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

禺垣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值