JavaEE精选-FileUpload

简介: JavaEE精选-FileUpload

准备工作

1.需要form表单,input type=file 组件

2.form表单方法post

3.form表单必须要设置enctype=multipart/form-data,可以上传除了表单数据(文本)以外的数据

4.如果要使用JavaBean来封装的话,那么这个file属性的组件的name要和封装的对象中的属性相同

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/servlet/upload" enctype="multipart/form-data" method="post">
    <input type="text" name="username"><br>
    <input type="password" name="password"><br>
    <input type="file" name="image"><br>
    <input type="submit">
</form>
 </body>
</html>

此时注意,由于设置了enctype=multipart/form-data导致请求体报文的格式改变,那么就不能使用普通的读取方式了,否则会导致在二进制文件中写入字符而报错

------WebKitFormBoundaryrYApx85v3VoXeztu
Content-Disposition: form-data; name="username"
admin
------WebKitFormBoundaryrYApx85v3VoXeztu
Content-Disposition: form-data; name="password"
admin123
------WebKitFormBoundaryrYApx85v3VoXeztu
Content-Disposition: form-data; name="image"; filename="1.txt"
Content-Type: text/plain
hello  你好
------WebKitFormBoundaryrYApx85v3VoXeztu--

必须要剔除分隔符的部分,需要引入第三方组件来解决

使用组件完成文件上传

使用组件整体的思路:

  • 首先需要判断请求是否包含上传的文件,否则使用该组件没有意义
boolean multipartContent = ServletFileUpload.isMultipartContent(request);
  • 创建工厂,设置文件缓存,获取upload对象
DiskFileItemFactory factory = new DiskFileItemFactory();//创建工厂
ServletContext servletContext = getServletContext();//获取Context域,用于缓存
File repository = (File)servletContext.getAttribute("javax.servlet.context.tempdir");//创建一个缓存的中转站
factory.setRepository(repository);
ServletFileUpload upload = new ServletFileUpload(factory);//利用工厂创建一个upload对象,功能是帮我们处理请求报文中上传的部分
upload.setHeaderEncoding("utf-8");
  • 使用upload对象对请求报文进行解析,将每一个input框中的内容解析成FileItem,得到的是一个List
  • item实际上就是input中上传的文本参数或者是文件,根据不同的文件来实现具体的业务逻辑,分发给不同的方法来进行处理
try {
    List<FileItem> items = upload.parseRequest(request);//处理请求报文对象
    for (FileItem item : items) {
        //item本质上是页面上的input框中包含的文本、文件
        if (item.isFormField()){
            //如果是普通的表单数据,作出表单数据的处理
            processFormField(item);
        }else {
            //处理上传文件
            processUploadFile(item);
        }
    }
} catch (FileUploadException e) {
    e.printStackTrace();
}
private void processFormField(FileItem item) {
    //具体处理表单数据的方法
    String fieldName = item.getFieldName();//相当于获取请求参数中的key
    String value = null; //获取value
    try {
        value = item.getString("utf-8");//处理表单数据的中文乱码
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    System.out.println(fieldName+":"+value);
}
  • 处理上传数据
private void processUploadFile(FileItem item) {
        String fieldName = item.getFieldName();//文件属性名
        String fileName = item.getName();//文件名
//        String contentType = item.getContentType();//获取文件类型名mni
//        long size = item.getSize();//文件大小
//        boolean inMemory = item.isInMemory();//是否在内存中
        String realPath = getServletContext().getRealPath("image/" + fileName);//获取该文件要存放在服务器硬盘上的绝对路径
        File file = new File(realPath);
        if (!file.getParentFile().exists()){
            //如果该文件的父路径不存在,那么需要进行创建
            file.getParentFile().mkdirs();
        }
        try {
            item.write(file); //直接将该item写入硬盘
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

中文乱码

表单中文乱码

//表单中文乱码的解决方案
value = item.getString("utf-8");

setEncoding失效,因为此时文件的格式已经变了,之前都是key=value

上传的文件名中文乱码

//设置上传的文件名中文乱码
upload.setHeaderEncoding("utf-8");

将数据保存到Java Bean

思路:在具体分发的处理方法中,传入一个map对象,用于保存键值对,键可以设置为JAVA Bean中的属性名,值设置为一个object,用于保存具体的参数类型;最后在所有的Item处理完毕后,将map使用BeanUtils进行处理,就完成了封装

package com.fh.upload;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@WebServlet("/upload2")
public class UploadServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
//        request.setCharacterEncoding("utf-8");
        boolean multipartContent = ServletFileUpload.isMultipartContent(request);//判断是否有上传的文件
        if (!multipartContent){
            //如果不存在该文件,那就直接返回
            System.out.println("你没有上传文件!");
            return;
        }
        DiskFileItemFactory factory = new DiskFileItemFactory();//创建工厂
        ServletContext servletContext = getServletContext();//获取Context域,用于缓存
        File repository = (File)servletContext.getAttribute("javax.servlet.context.tempdir");//创建一个缓存的中转站
        factory.setRepository(repository);
        ServletFileUpload upload = new ServletFileUpload(factory);//利用工厂创建一个upload对象,功能是帮我们处理请求报文中上传的部分
        upload.setHeaderEncoding("utf-8"); //解决上传文件名的中文乱码
        Map<String,Object> map = new HashMap<>();
        User user = new User();
        try {
            List<FileItem> items = upload.parseRequest(request);//处理请求报文对象
            for (FileItem item : items) {
                //item本质上是页面上的input框中包含的文本、文件
                if (item.isFormField()){
                    //如果是普通的表单数据,作出表单数据的处理
                    processFormField(item,map);
                }else {
                    //处理上传文件
                       processUploadFile(item,map);
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
        try {
            BeanUtils.populate(user,map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        getServletContext().setAttribute("user",user);//将user传到共享域
        response.setHeader("refresh","6;url="+request.getContextPath()+"/view");
    }
    private void processUploadFile(FileItem item, Map<String, Object> map) {
        String fieldName = item.getFieldName();//文件属性名
        String fileName = item.getName();//文件名
//        String contentType = item.getContentType();//获取文件类型名mni
//        long size = item.getSize();//文件大小
//        boolean inMemory = item.isInMemory();//是否在内存中
        String relativePath  = "image/"+fileName;
        String realPath = getServletContext().getRealPath(relativePath);//获取该文件要存放在服务器硬盘上的绝对路径
        File file = new File(realPath);
        if (!file.getParentFile().exists()){
            //如果该文件的父路径不存在,那么需要进行创建
            file.getParentFile().mkdirs();
        }
        try {
            item.write(file); //直接将该item写入硬盘
            map.put("img",relativePath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private void processFormField(FileItem item, Map<String, Object> map) {
        //具体处理表单数据的方法
        String fieldName = item.getFieldName();//相当于获取请求参数中的key
        String value = null; //获取value
        try {
            value = item.getString("utf-8");//处理表单数据的中文乱码
        } catch (UnsupportedEncodingException e)    {
            e.printStackTrace();
        }
        map.put(fieldName,value);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
}

工具类

package com.fh.upload;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class FileUploadUtil {
    public static Map<String, Object> parseRequest(HttpServletRequest request){
        //解析请求报文,终极目标是返回一个该请求报文中所有参数的列表,并完成文件上传的工作
        DiskFileItemFactory factory = new DiskFileItemFactory();//创建工厂
        ServletContext servletContext = request.getServletContext();//获取Context域,用于缓存
        File repository = (File)servletContext.getAttribute("javax.servlet.context.tempdir");//创建一个缓存的中转站
        factory.setRepository(repository);
        ServletFileUpload upload = new ServletFileUpload(factory);//利用工厂创建一个upload对象,功能是帮我们处理请求报文中上传的部分
        upload.setHeaderEncoding("utf-8"); //解决上传文件名的中文乱码
        Map<String,Object> map = new HashMap<>();
        try {
            List<FileItem> items = upload.parseRequest(request);//处理请求报文对象
            for (FileItem item : items) {
                //item本质上是页面上的input框中包含的文本、文件
                if (item.isFormField()){
                    //如果是普通的表单数据,作出表单数据的处理
                    processFormField(item,map);
                }else {
                    //处理上传文件
                    processUploadFile(item,map,request);
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
        return map;
    }
    private static void processUploadFile(FileItem item, Map<String, Object> map, HttpServletRequest request) {
        String fieldName = item.getFieldName();//文件属性名
        String fileName = item.getName();//文件名
        fileName = UUID.randomUUID().toString() + "-" + fileName; //随机生成一个文件名,防止重复
        //对文件上传进行散列
        int hashCode = fileName.hashCode();
        String hexString = Integer.toHexString(hashCode); //生成一个16进制的哈希值,每一位都分别创建子目录,完成散列
        char[] chars = hexString.toCharArray();
        String basePath = fieldName; //总的一个父路径,所有下属的文件夹都放在这个父路径里,根据不同的文件类型生成
        for (char aChar : chars) {
            basePath = basePath + "/" + aChar;
        }
        String relativePath = basePath + "/" + fileName; //最终用文件总的父路径拼接文件名,那么就得到了文件要存放在硬盘上的相对路径
        //需要根据相对路径获取存储到服务器磁盘的绝对路径,显然需要一个request对象
        String realPath = request.getServletContext().getRealPath(relativePath);
        File file = new File(realPath);
        if (!file.getParentFile().exists()){
            //父路径不存在,那就创建
            file.getParentFile().mkdirs();
        }
        try {
            item.write(file);
            map.put(fieldName,relativePath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static void processFormField(FileItem item, Map<String, Object> map) {
        String name = item.getFieldName();
        String value = null;
        try {
            //表单中文乱码的解决方案
            value = item.getString("utf-8");
            map.put(name, value);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}
目录
相关文章
|
6月前
|
域名解析 缓存 网络协议
JavaEE精选-Web组件
JavaEE精选-Web组件
42 1
|
6月前
|
XML 网络协议 Java
JavaEE精选-Servlet
JavaEE精选-Servlet
35 0
|
6月前
|
Java 应用服务中间件
JavaEE精选-Response
JavaEE精选-Response
33 0
|
6月前
|
Java API 数据库
JavaEE精选-Request
JavaEE精选-Request
45 0
|
6月前
|
SQL 缓存 安全
【JavaEE进阶】 #{}和${}
【JavaEE进阶】 #{}和${}
|
缓存 easyexcel Java
狂神说POI,EasyExcel笔记及源码资料(一)
狂神说POI,EasyExcel笔记及源码资料(一)
895 0
狂神说POI,EasyExcel笔记及源码资料(一)
|
JSON 前端开发 easyexcel
这年头谁还用POI,快来使用国人写的EasyExcel吧,SpringBoot+EasyExcel的快速入门
这年头谁还用POI,快来使用国人写的EasyExcel吧,SpringBoot+EasyExcel的快速入门
这年头谁还用POI,快来使用国人写的EasyExcel吧,SpringBoot+EasyExcel的快速入门
|
Java
struts2实现的文件上传下载案例(一)、FileUpLoad
struts2实现的文件上传下载案例(一)、FileUpLoad
247 0
struts2实现的文件上传下载案例(一)、FileUpLoad
|
JSON Java 编译器
告别BeanUtils,Mapstruct从入门到精通
如果你现在还在使用BeanUtils,看了本文,也会像我一样,从此改用Mapstruct。
1113 0
告别BeanUtils,Mapstruct从入门到精通
|
前端开发 JavaScript Oracle
Jave&JavaEE1|学习笔记
快速学习Jave&JavaEE1
132 0
Jave&JavaEE1|学习笔记