JavaWeb(十) 文件上传

文件上传概述

1 文件上传的作用

在现实中,我们经常需要客户端向服务器上传一些资源,比如,我们使用QQ时,可以设置头像,那我们就需要从我们本地电脑(客户端)向QQ服务器来上传我们喜欢的头像.还比如现在很流行的百度云盘,也需要我们往百度云盘的服务器上传资源,比如小电影,小图片等等.

2 文件上传对页面的要求

上传文件的要求比较多,需要记一下:

  1. 必须使用表单,而不能是超链接;

  2. 表单的method必须是POST,而不能是GET;

  3. 表单的enctype必须是multipart/form-data;

  4. 在表单中添加file表单字段,即<input type="file”…/>

   <form action="${pageContext.request.contextPath }/FileUploadServlet" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="username"/><br/>
    文件1:<input type="file" name="file1"/><br/>
    文件2:<input type="file" name="file2"/><br/>
    <input type="submit" value="提交"/>
   </form>

“文件上传表单”和“普通文本表单”的区别:

  • 文件上传表单的enctype=”multipart/form-data”,表示多部件表单数据;

  • 普通文本表单可以不设置enctype属性:

  • 当method=”post”时,enctype的默认值为application/x-www-form-urlencoded,表示使用url编码正文;

  • 当method=”get”时,enctype的默认值为null,没有正文,所以就不需要enctype了。

3 文件上传对Servlet的要求

当提交的表单是文件上传表单时,那么对Servlet也是有要求的。

首先我们要肯定一点,文件上传表单的数据也是被封装到request对象中的。

request.getParameter(String)方法获取指定的表单字段字符内容,但文件上传表单已经不在是字符内容,而是字节内容,所以失效。

这时可以使用request的getInputStream()方法获取ServletInputStream对象,它是InputStream的子类,这个ServletInputStream对象对应整个表单的正文部分(从第一个分隔线开始,到最后),这说明我们需要的解析流中的数据。当然解析它是很麻烦的一件事情,而Apache已经帮我们提供了解析它的工具:commons-fileupload。

1 fileupload概述

fileupload是由apache的commons组件提供的上传组件。它最主要的工作就是帮我们解析request.getInputStream()。

fileupload组件需要的JAR包有:

commons-fileupload.jar,核心包;

commons-io.jar,依赖包。

2 fileupload简单应用

  fileupload的核心类有:DiskFileItemFactory、ServletFileUpload、FileItem。

使用fileupload组件的步骤如下:

  1. 创建工厂类DiskFileItemFactory对象:DiskFileItemFactory factory = new DiskFileItemFactory()

  2. 使用工厂创建解析器对象:ServletFileUpload fileUpload = new ServletFileUpload(factory)

  3. 使用解析器来解析request对象:List<FileItem> list = fileUpload.parseRequest(request)

隆重介绍FileItem类,它才是我们最终要的结果。一个FileItem对象对应一个表单项(表单字段)。一个表单中存在文件字段和普通字段,可以使用FileItem类的isFormField()方法来判断表单字段是否为普通字段,如果不是普通字段,那么就是文件字段了。

  • String getName():获取文件字段的文件名称;

  • String getString():获取字段的内容,如果是文件字段,那么获取的是文件内容,当然上传的文件必须是文本文件;

  • String getFieldName():获取字段名称,例如:<input type="text" name="username"/>,返回的是username;

  • String getContentType():获取上传的文件的类型,例如:text/plain。

  • int getSize():获取上传文件的大小;

  • boolean isFormField():判断当前表单字段是否为普通文本字段,如果返回false,说明是文件字段;

  • InputStream getInputStream():获取上传文件对应的输入流;

  • void write(File):把上传的文件保存到指定文件中。

3 简单上传示例

写一个简单的上传示例:

  1. 表单包含一个用户名字段,以及一个文件字段;

  2. Servlet保存上传的文件到uploads目录,显示用户名,文件名,文件大小,文件类型。

第一步:

完成index.jsp,只需要一个表单。注意表单必须是post的,而且enctype必须是mulitpart/form-data的。

  <form action="${pageContext.request.contextPath }/FileUploadServlet" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="username"/><br/>
    文件1:<input type="file" name="file1"/><br/>
    <input type="submit" value="提交"/>
   </form>

第二步:

完成FileUploadServlet

public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 因为要使用response打印,所以设置其编码
        response.setContentType("text/html;charset=utf-8");
        
        // 创建工厂
        DiskFileItemFactory dfif = new DiskFileItemFactory();
        // 使用工厂创建解析器对象
        ServletFileUpload fileUpload = new ServletFileUpload(dfif);
        try {
            // 使用解析器对象解析request,得到FileItem列表
            List<FileItem> list = fileUpload.parseRequest(request);
            // 遍历所有表单项
            for(FileItem fileItem : list) {
                // 如果当前表单项为普通表单项
                if(fileItem.isFormField()) {
                    // 获取当前表单项的字段名称
                    String fieldName = fileItem.getFieldName();
                    // 如果当前表单项的字段名为username
                    if(fieldName.equals("username")) {
                        // 打印当前表单项的内容,即用户在username表单项中输入的内容
                        response.getWriter().print("用户名:" + fileItem.getString() + "<br/>");
                    }
                } else {//如果当前表单项不是普通表单项,说明就是文件字段
                    String name = fileItem.getName();//获取上传文件的名称
                    // 如果上传的文件名称为空,即没有指定上传文件
                    if(name == null || name.isEmpty()) {
                        continue;
                    }
                    // 获取真实路径,对应${项目目录}/uploads,当然,这个目录必须存在
                    String savepath = this.getServletContext().getRealPath("/uploads");
                    // 通过uploads目录和文件名称来创建File对象
                    File file = new File(savepath, name);
                    // 把上传文件保存到指定位置
                    fileItem.write(file);
                    // 打印上传文件的名称
                    response.getWriter().print("上传文件名:" + name + "<br/>");
                    // 打印上传文件的大小
                    response.getWriter().print("上传文件大小:" + fileItem.getSize() + "<br/>");
                    // 打印上传文件的类型
                    response.getWriter().print("上传文件类型:" + fileItem.getContentType() + "<br/>");
                }
            }
        } catch (Exception e) {
            throw new ServletException(e);
        } 
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

在下张仙人

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

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

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

打赏作者

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

抵扣说明:

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

余额充值