文件上传

上传的准备工作

  • 表单method必须为post
  • 提供file组件
  • 设置form标签的enctype属性为multipart/form-data,如果没有设置enctype属性,浏览器是无法将文件自身传递到服务端的(enctype默认为application/x-www-form-urlencoded)
<form action="fileupload.do" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="username"/><br/>
    密码:<input type="password" name="password"/><br/>
    上传文件:<input name="file" type="file" /><br/>
    <input type="submit"/>
</form>

上传时HTTP协议的格式

  1. enctype为application/x-www-form-urlencoded时

    从表单发送数据到服务器,数据是以键值对的形式存放在请求体中发送到服务器的。

    使用google浏览器的自动抓包(F12),可以查看表单数据在HTTP协议中的格式:

    img

    request.getParameter(name)是以键值对的形式获取值的,所以可以通过该方法得到表单中的数据。可以得到文件名,但是得不到文件!

  2. enctype为multipart/form-data时

    在上传时,multipart/form-data请求会把表单的数据处理为一条消息,以标签为单元,用分隔符(boundary)分开。既可以上传普通表单数据,也可以上传文件。content-disposition,用来说明字段的一些信息。当上传的字段是文件时,会有Content-Type来表明文件类型。

    使用google浏览器查看上传时表单数据在HTTP协议的格式:

    img

    表单数据在HTTP协议中不是以键值对形式存在的,所以在服务器端是无法通过request.getParameter(name)获取数据的。

    可以利用分隔符boundary和Content-type属性自己编写代码实现文件上传。

  3. 在服务器端查看从客户端传来的表单数据

    可以使用request.getInputStream()来获取从客户端传来的数据,可以通过下面的代码把传来的数据输出到控制台:

      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            InputStream is = request.getInputStream();
            int i = is.read();
            while(i != -1) {
                char c = (char)i;
                System.out.print(c);
                i = is.read();
            }
        }
    

    在没有设置enctype属性时,传到服务器的数据为:

    img

    文件上传时,传到服务器的数据为:

    img

    其中的乱码为二进制数据,也就是要上传的文件。

FileUpload实现文件上传

FileUpload 是 Apache commons下面的一个子项目,用来实现Java环境下面的文件上传功能。

使用FileUpload需要两个jar包的支持,这里FileUpload版本为:commons- fileupload-1.2.1,Commons IO版本为:commons-io-1.4。

客户端代码:

<body>
<form action="fileupload.do" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="username"/><br/>
    密码:<input type="password" name="password"/><br/>
    上传文件:<input name="file" type="file" /><br/>
    <input type="submit"/>
</form>
</body>

服务器端代码为:

@WebServlet(name = "FileServlet",urlPatterns = "/fileupload.do")
public class FileServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        //判断是否支持文件上传
        boolean isMultipart  = ServletFileUpload.isMultipartContent(request);
        if(!isMultipart) {
            throw new RuntimeException("不支持文件上传");
        }
        //创建一个磁盘工厂
        DiskFileItemFactory  factory=new DiskFileItemFactory();
        //配置缓存库
        ServletContext servletContext = this.getServletConfig().getServletContext();
        File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
        factory.setRepository(repository);
        //解析数据
        ServletFileUpload fileUpload=new ServletFileUpload(factory);
        List<FileItem> items = null;
        try {
            items=fileUpload.parseRequest(request);
        } catch (FileUploadException e) {
            e.printStackTrace();
        }

        for(FileItem item : items) {
            if (item.isFormField()) {
                String name = item.getFieldName();
                String value = item.getString();
                System.out.println(name + " " + value);
            } else {
                //取文件名
                String fileName = item.getName();
                fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
                //取文件拓展名
                String exten = fileName.substring(fileName.lastIndexOf("."));
                //新文件名,防止文件重名
                String newFileName = UUID.randomUUID().toString().replace("-", "") + exten;
                //把文件写入到upload文件夹下
                String path = this.getServletConfig().getServletContext().getRealPath("/");
                String directPath = path + "upload\\" + newFileName;
                File file = new File(directPath);
                OutputStream os = new FileOutputStream(file);
                InputStream is = item.getInputStream();
                byte[] b = new byte[1024];
                int len = 0;
                while ((len = is.read(b)) != -1) {
                    os.write(b, 0, len);
                }
                os.close();
                is.close();
            }
        }
        request.getRequestDispatcher("ok.jsp").forward(request, response);
    }

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

文件下载

@WebServlet(name = "DownloadServlet", urlPatterns = "/download.do")
public class DownloadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 获得要下载的文件的名称
        String filename = request.getParameter("filename");
        // 告诉客户端该文件不是直接解析,而是以附件形式打开(下载)
        response.setHeader("Content-Disposition", "attachment;filename=" + filename);
        // 获取文件的绝对路径
        String path = this.getServletContext().getRealPath("download/" + filename);
        // 获得该文件的输入流
        InputStream in = new FileInputStream(path);
        // 获得输出流--通过response获得的输出流 用于向客户端写内容
        ServletOutputStream out = response.getOutputStream();
        // 文件拷贝代码
        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len = in.read(buffer)) != -1) {
            out.write(buffer, 0, len);
        }
        in.close();
        out.close();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
posted on 2018-10-13 13:03  kindleheart  阅读(304)  评论(0编辑  收藏  举报