文件上传下载

前端文件上传

这里说的文件上传和文件下载都是针对客户端进行的操作

  1. 使用如下jsp代码,通过Servlet获取表单数据,是否可以获取到文件信息

    <%--
      Created by IntelliJ IDEA.
      User: carl
      Date: 2021/10/9
      Time: 15:46
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>文件上传</title>
    </head>
    <body>
        <form method="post" action="http://127.0.0.7:8080/JavaWeb/myServlet">
            <input type="text" name="username"/><br/>
            <input type="file" name="upload"/><br/>
            <input type="submit" name="提交"/>
        </form>
    </body>
    </html>
    
    package com.carl.controller;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * @author :Carl_蔡先生
     * @version :JDK1.8
     * @description:TODO
     * @date :2021/10/8 16:06
     * @month_name :10月
     * @week :
    */
    public class MyServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("我是get");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String username = req.getParameter("username");
            String upload = req.getParameter("upload");
            System.out.println(upload);
        }
    }
    
  2. 配置web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        <servlet>
            <servlet-name>MyServlet</servlet-name>
            <servlet-class>com.carl.controller.UploadServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>MyServlet</servlet-name>
            <url-pattern>/myServlet</url-pattern>
        </servlet-mapping>
        <listener>
            <listener-class>com.carl.listener.MyListener</listener-class>
        </listener>
    </web-app>
    

    很明显:当我们使用Servlet获取name=upload的内容时,获取的只是文件名,通过浏览器我们不难发现,上传的只是一个文件名
    在这里插入图片描述

后端获取前端上传文件流

  1. 实现真正的文件上传
    在form表单属性中加上enctype="multipart/form-data"

    multipart/form-data:表示提交的数据,会以多段的形式进行拼接,然后以二进制流的形式发送给服务器

    在这里插入图片描述

  2. 如何证实是以流的形式将数据请求发送到服务器了
    首先:我们添加了multipart/form-data后,无法再使用request.getParameter这个方法获取到任何信息,因为传输的方式变了
    其次:浏览器以流的形式发送请求,势必服务器也要用流的方式进行接收

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        ServletInputStream inputStream = req.getInputStream();
        byte[] b=new byte[1024];
        int len = inputStream.read(b);
        System.out.println(new String(b,0,len));
    
    }
    ------WebKitFormBoundaryidn5jp863QXWwCps
    Content-Disposition: form-data; name="username"
    
    15572115923@163.com
    ------WebKitFormBoundaryidn5jp863QXWwCps
    Content-Disposition: form-data; name="upload"; filename="DSC08260.jpg"
    Content-Type: image/jpeg
    

    在这里插入图片描述

    解析:
    在这里插入图片描述

    上图所示是请求体
    在这里插入图片描述

    上图的内容是二进制文件的内容
    在这里插入图片描述
    在这里插入图片描述

获取文件上传信息

  1. 导入jar包–fileupload包依赖于io的jar包

  2. 常用的类和方法

    ServletFileUpload类:用于解析上传数据
        常用方法:
        boolean mc = ServletFileUpload.isMultipartContent(req);判断当前请求数据是否是以多段的流形式进行传输的
        List<FileItem> list = servletFileUpload.parseRequest(req);用于解析上传的数据
      ServletFileUpload servletFileUpload = new ServletFileUpload(fif);构造器:内部要传输一个FileItemFactory对象,而FileItemFactory是一个接口,子类中只有DiskFileItemFactory实现类,另一个已经过时了,因此,创建的该FileItemFactory需要使用多态的方式FileItemFactory fif=new DiskFileItemFactory();
    FileItem类:表示每一个表单项
      常用方法:
      boolean isFormField():判断当前这个表单项是否是普通的表单项,true则表示是普通类型的表单项,false表示上传的文件类型
      String getFieldName():获取表单项的name属性值
      String getString():获取当前表单项的值value
      String getName():获取上传文件的文件名
      void write(file):将上传的文件写入到参数file所指向的硬盘位置
    

    在这里插入图片描述

    req.setCharacterEncoding("UTF-8");
    boolean mc = ServletFileUpload.isMultipartContent(req);
    System.out.println(mc);//true
    if (mc) {
        FileItemFactory fif=new DiskFileItemFactory();
        ServletFileUpload servletFileUpload = new ServletFileUpload(fif);
        List<FileItem> list = null;
        try {
            list = servletFileUpload.parseRequest(req);
            for (FileItem fileItem : list) {
                if (fileItem.isFormField()) {
                    System.out.println("表单项的name属性值:"+fileItem.getFieldName());
                    System.out.println("表单项的value属性值"+fileItem.getString("UTF-8"));
    
                }else{
                    System.out.println("表单项的name属性值:"+fileItem.getFieldName());
                    System.out.println("表单项的value属性值:"+fileItem.getName());
                    fileItem.write(new File("E:\\a.jpg"));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    

文件下载

response.getOutputStream();
servletContext.getResourceAsStream();
servletContext.getMimeType();
response.setContextType();
文件下载一:从服务器获取图片供客户端下载

预先,需要编写一个Servlet用于下载,如果是直接访问,则最好设置为get请求,网页链接的方式都是GET请求

配置web.xml

  1. 获取需要下载的文件在浏览器中的数据类型(MIME)
    首先获取文件的类型,需要使用ServletContext域对象中的getMimeType()方法

    ServletContext servletContext = getServletContext();
    
    String downloadFileName="a.jpg";
    String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
    
    resp.setContentType(mimeType);
    

    第四步:告诉浏览器,我这个文件是用来干什么的;Content-Disposition是MIME协议的扩展,是一个响应头

    Content-Disposition是一个指示浏览器响应的内容应该以何种形式进行展示

    有两种方式:内联和附件;

    • 内联是将响应内容作为网页的一部分进行展示;

    • 附件是将响应的内容支持下载的形式保存到本地;详细描述可参考该地址

    resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode("中国.jpg", "UTF-8"));
    
  2. 获取输入流:将该文件从服务器本地获取输入流,输入到ServletContext对象中

    InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadFileName);
    
  3. 获取输出流:获取Response对象的输出流–因为需要Response将文件通过流的方式输出给浏览器

    ServletOutputStream outputStream = resp.getOutputStream();
    
  4. 将输入流的文件信息copy给输出流:将ServletContext对象中的输入流获取的文件信息,复制到输出流中,通过输出流反馈给浏览器

    int copy = IOUtils.copy(resourceAsStream, outputStream);
    
文件下载二:从客户端发送下载请求,提交给服务器进行下载

我们可以根据用户上传的图片,下载到服务器本地,再通过请求重定向的方式,进行下载–请求重定向就必须将被重定向的Servlet设置为Get请求

package com.carl.controller;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * @author :Carl_蔡先生
 * @version :JDK1.8
 * @description:TODO
 * @date :2021/10/8 16:06
 * @month_name :10月
 * @week :
*/
public class UploadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        req.setCharacterEncoding("UTF-8");
        boolean mc = ServletFileUpload.isMultipartContent(req);
        System.out.println(mc);//true
        if (mc) {
            FileItemFactory fif=new DiskFileItemFactory();
            ServletFileUpload servletFileUpload = new ServletFileUpload(fif);
            List<FileItem> list = null;
            try {
                list = servletFileUpload.parseRequest(req);
                for (FileItem fileItem : list) {
                    if (fileItem.isFormField()) {
                        System.out.println("表单项的name属性值:"+fileItem.getFieldName());
                        System.out.println("表单项的value属性值"+fileItem.getString("UTF-8"));

                    }else{
                        System.out.println("表单项的name属性值:"+fileItem.getFieldName());
                        System.out.println("表单项的value属性值:"+fileItem.getName());
                        fileItem.write(new File("E:\\文档\\Java_WorkSpace\\JavaWeb\\web\\file\\a.jpg"));
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        resp.sendRedirect("downloadServlet");

    }
}
package com.carl.controller;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.IOUtils;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.time.chrono.MinguoEra;
import java.util.List;

/**
 * @author :Carl_蔡先生
 * @version :JDK1.8
 * @description:TODO
 * @date :2021/10/9 19:42
 * @month_name :10月
 * @week :
*/
public class DownloadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取Servlet上下文对象
        ServletContext servletContext = getServletContext();
        String downloadFileName="a.jpg";
        //通过Servlet上下文获取/file/a.jpg文件的类型
        String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
        //将该类型传递给响应对象
        resp.setContentType(mimeType);
        //设置响应头Content-Disposition:attachment;filename,这是为了告诉浏览器attachment是一个附件,一个需要下载的文件,file后面跟随的就是需要下载的文件名
        //URLEncoder.encode()标记UTF-8编码,告诉浏览器该文件名按UTF-8进行解析,但是不同浏览器可能不同,最好是用Base64编解码操作
        resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode("中国.jpg", "UTF-8"));
        //获取请求的输入流
        InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadFileName);
        //获取响应的输出流
        ServletOutputStream outputStream = resp.getOutputStream();
        int copy = IOUtils.copy(resourceAsStream, outputStream);
    }
}
  • 19
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Carl·杰尼龟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值