javaweb上传文件

介绍

上传文件是最常用的功能之一,如网购评论时要发图片,报考网站要上传个人信息等

实现html

创建 upload.jsp,关键内容如下:

<form method="post" enctype="multipart/form-data" action="upload">
    上传图片:<input type="file" name="img"><br>
    描述:<input type="text" name="descrip"><br>
    <input type="submit">
</form>

关键:

  • method="post" 必须是 post 方法

  • enctype="multipart/form-data":enctype 是表单请求正文的类型,上传文件必须设置,表示以 流 的方式将数据发送给服务器

  • <input type="file" name="img">:上传文件控件,注意名字

依赖jar包

像之前 request.getParameter() 的方式接收数据,是接收不到的

因为: 浏览器是以 流 的方式向服务发送数据,服务器也需要以 流 的方式 接收数据

以 流 的方式接收数据,比较复杂,好在 Apache 已经开发好了 jar包,我们直接使用即可:

  • commons-fileupload.jar:处理文件上传
    下载地址

  • commons-io.jar:commons-fileupload.jar依赖该jar包
    下载地址

常用类说明

FileItemFactory 和 DiskFileItemFactory

用于实例化 ServletFileUpload 类对象

FileItemFactory fif=new DiskFileItemFactory();
ServletFileUpload sfu=new ServletFileUpload(fif);

ServletFileUpload 类

用于处理上传数据

常用方法:

  • boolean isMultipartContext(HttpServletRequest request):判断是否文件上传

  • Map<String,List<FileItem> parseRequest(HttpServletRequest request):解析上传数据,返回 Map

    • Map中的key:是表单控件的 name 属性值

    • Map中的value:是List<FileItem>类型,表单控件的 value 值。一般控件,那么该 List 只有一个元素,如果 checkbox 控件,则是多个元素

FileItem类

一个 FileItem对象 代表表单中一个控件,可以表示普通控件,也可以表示上传文件控件

常用方法:

  • String getFieldName():返回表单控件的 name 属性值

  • String getString():返回表单控件的 value 值。如果是上传文件对象,是乱码,无意义。

  • String getName():如果是上传文件对象,那么返回上传文件的名字,否则为null

  • void write(File file):将文件写入到指定位置

  • boolean isFormField():true表示普通表单控件,false表示文件控件

实现Servlet

有缺点:不能上传同名文件

package servlet;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;

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 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;


@WebServlet(urlPatterns="/upload")
public class UploadServlet extends HttpServlet{

    // 上传文件存储目录
    public static final String UPLOAD_PATH = "upload";

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //判断是否文件上传
        boolean isMC=ServletFileUpload.isMultipartContent(req);
        if(isMC){
            FileItemFactory fif=new DiskFileItemFactory();
            ServletFileUpload sfu=new ServletFileUpload(fif);
            // 构造保存上传文件的路径
            String uploadPath = getServletContext().getRealPath("/"+UPLOAD_PATH) ;
            //在开发时,是开发工具集成tomcat,所以不在本工程目录下
            System.out.println("上传文件路径:"+uploadPath);

            //通过File类对象,判断该目录是否存在,如果不存在,就创建该目录
            File uploadPathFile=new File(uploadPath);
            if(!uploadPathFile.exists()){ //判断是否存在
                uploadPathFile.mkdirs(); // 创建目录
            }
            try {
                //传入request,解析出上传文件
                Map<String, List<FileItem>> map=sfu.parseParameterMap(req);
                List<FileItem> imgs=map.get("img"); //获取上传的文件
                List<FileItem> descrips=map.get("descrip"); //获取控件的值
//              req.getParameter("descrip")//上传文件,不能通过这种方式获取

                if(imgs!=null && !imgs.isEmpty()){
                    FileItem img=imgs.get(0); // 获取第一个文件(暂且不考虑上传多个文件)
                    File uploadFile=new File(uploadPathFile, img.getName());//拼装要保存文件的目录
                    img.write(uploadFile);// 将上传的文件,写入到该目录
                }
                //获取表单控件的值
                if(descrips!=null && !descrips.isEmpty()){
                    String descrip=descrips.get(0).getString("utf-8");
                    System.out.println(descrip);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //根据情况,跳转到成功页面,或者输出一段文字
    }


}

实现 Servlet

可以上传同名文件,会生成 新的文件名,文件名由 UUID生成,后缀是 原文件名的后缀

@WebServlet(urlPatterns="/upload")
public class UploadServlet extends HttpServlet{

    // 上传文件存储目录
    public static final String UPLOAD_PATH = "upload";

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //判断是否文件上传
        boolean isMC=ServletFileUpload.isMultipartContent(req);
        if(isMC){
            FileItemFactory fif=new DiskFileItemFactory();
            ServletFileUpload sfu=new ServletFileUpload(fif);
            // 构造保存上传文件的路径
            String uploadPath = getServletContext().getRealPath("/"+UPLOAD_PATH) ;
            //在开发时,是开发工具集成tomcat,所以不在本工程目录下
            System.out.println("上传文件路径:"+uploadPath);

            //通过File类对象,判断该目录是否存在,如果不存在,就创建该目录
            File uploadPathFile=new File(uploadPath);
            if(!uploadPathFile.exists()){ //判断是否存在
                uploadPathFile.mkdirs(); // 创建目录
            }
            try {
                //传入request,解析出上传文件
                Map<String, List<FileItem>> map=sfu.parseParameterMap(req);
                List<FileItem> imgs=map.get("img"); //获取上传的文件
                List<FileItem> descrips=map.get("descrip"); //获取控件的值
//              req.getParameter("descrip")//上传文件,不能通过这种方式获取

                if(imgs!=null && !imgs.isEmpty()){
                    FileItem img=imgs.get(0); // 获取第一个文件(暂且不考虑上传多个文件)

                    //重命名文件名字,防止文件名同名
                    String fileName=img.getName();
                    String newFileName = getNewFileName(fileName);

                    File uploadFile=new File(uploadPathFile,newFileName );//拼装要保存文件的目录
                    img.write(uploadFile);// 将上传的文件,写入到该目录
                }
                //获取表单控件的值
                if(descrips!=null && !descrips.isEmpty()){
                    String descrip=descrips.get(0).getString("utf-8");
                    System.out.println(descrip);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //根据情况,跳转到成功页面,或者输出一段文字
    }

    /**
     * 实现新的文件名,文件名由 UUID生成,后缀是 原文件名的后缀
     * @param oldFileName
     * @return
     */
    private String getNewFileName(String oldFileName){

        //获取原文件的后缀
        int pos=oldFileName.lastIndexOf(".");//从右往左找到第一个 .
        String suffix=oldFileName.substring(pos);
        //用uuid作为文件名,后面还要拼装后缀
        String newFileName=UUID.randomUUID().toString().replace("-", "")+suffix;

        return newFileName;

    }

}

原文出处:/show_1IXtMnb6lu8.html