JavaWeb上传文件

JavaEE 专栏收录该内容
18 篇文章 0 订阅

JavaWeb—上传文件

前期准备

  • 我们一般通过流来获取上传的文件(request.getInputstream),但是原始的文件上传流的获取很麻烦,所以我在这里用Apache的文件上传组件来实现文件的上传

  • 我们需要准备两个jar包(下载最新的):

  • 在项目中导入jar包:(导完包记得修复路径)
    在这里插入图片描述

修复路径:
在这里插入图片描述

代码实现

  • 注意

    • 上传的文件应该放在WEB-INF目录下,用户 无法直接访问这个目录,可以保证服务器的安全
    • 为了防止同名覆盖情况出现,需要给上传的文件一个唯一的文件名
    • 需要限制上传文件的大小和类型
    • 注意乱码问题
    • 设置临时文件存储目录
  • 前端提交页面

    • form表单的method属性值应为post,因为get不能传送大数据的文件,而post没有上线,而且post相对更安全一些
    • form表单的enctype属性规定如何对表单数据进行编码,有三个值
      1.application/x-www-form-urlencoded—默认值
      2.multipart/form-data—当我们上传非文本的内容,比如图片、mp3和文件,用这个属性值
      3.text/plain—纯文本传输时,用这个值

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <style>
        body{
            background-color: antiquewhite;
        }
        p{

            color: darksalmon;
            font-size:30px;
        }
    </style>
</head>
<body>
    
<form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">

    <p>用户名:<input type="text" name="username"></p>
    <p>上传文件:<input type="file" name="file"></p>
    <p><input type="submit" value="提交"></p>

</form>

</body>
</html>
  • UploadServlet

    • ServletFileUpload类—用来处理上传的文件数据,将表单中的每个输入封装成一个FileItem对象
      • public void setSizeMax()—用来设置可以传送的文件的最大值
      • public void setFileSizeMax()—用来设置上传的单个文件的最大值
      • 创建ServletFileUpload对象时需要DiskFileItemFactory(创建FileItem 对象的工厂)对象
    • FileItem类
      • boolean isFormField()—判断FileItem类对象封装的数据是一个普通文本表单字段,还是一个文件表单字段
      • String getName()—用于获得文件上传字段中的文件名
      • InputStream getInputStream()—以流的形式返回上传文件的数据内容
      • void delete()—主要用于删除临时文件
    • ServletContext(servlet上下文)
      运行在JAVA虚拟机中的每一个Web应用程序都有一个与之相关的Servlet上下文(一对一)。可以通过getServletContext方法获得ServletContext对象。一个WEB应用程序中的所有Servlet共享同一个ServletContext对象,ServletContext提供对应用程序中所有Servlet所共有的各种资源和功能的访问。
    package priv.sehun.servlet;
    
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.FileUploadException;
    import org.apache.commons.fileupload.ProgressListener;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    import java.util.UUID;
    
    public class UploadServlet extends javax.servlet.http.HttpServlet {
        protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
            doGet(request,response);
        }
    
        protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
    
            try {
                //判断上传的表单是否带文件
                if(!ServletFileUpload.isMultipartContent(request)){
                    //如果是普通文本表单,直接返回
                    return;
                }
                //带文件的表单
    
                //创建上传文件的保存路径,建议在WEB-INF下,安全
                String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
                File file1 = new File(uploadPath);
                if(!file1.exists()){
                    file1.mkdir();
                }
    
                //临时路径,文件超出预期大小,放这
                String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
                File file = new File(tempPath);
                if(!file.exists()){
                    file.mkdir();
                }
                /*
                System.out.println("###"+this.getServletContext().getRealPath("/WEB-INF"));
                输出为:###D:\work\IDEAProjects\西部开源的代码\2019-7-20文件上传\out\artifacts\2019_7_20_war_exploded\WEB-INF
                */
    
    
                //1.创建DiskFileItemFactory对象,处理文件大小路径等
                DiskFileItemFactory factory = getFactory(file);
    
                //2.获取ServletFileUpload
                ServletFileUpload upload = getServletFileUpload(factory);
    
                //3.处理上传的文件
                String msg = upLoadParseRequest(upload,request,uploadPath);
    
                request.setAttribute("msg",msg);
                request.getRequestDispatcher("msg.jsp").forward(request,response);
            } catch (FileUploadException e) {
                e.printStackTrace();
            }
    
    
    
        }
    
        private DiskFileItemFactory getFactory(File file) {
    
            DiskFileItemFactory factory = new DiskFileItemFactory();
    
            //设置一个缓冲区,若文件大小超过缓冲区,放到临时路径
            factory.setSizeThreshold(1024*1024*5);
            factory.setRepository(file);
            return factory;
        }
        private ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
            ServletFileUpload upload = new ServletFileUpload(factory);
            //监听文件上传进度
            upload.setProgressListener(new ProgressListener() {
                @Override
                public void update(long pBytesRead, long pContentlenth, int pItems) {
                    //pContentlenth:文件大小
                    //pBytesRead:已读取文件大小
                    System.out.println("总大小:"+pContentlenth+"   已上传:"+pBytesRead);
                }
            });
            //防止乱码
            upload.setHeaderEncoding("UTF-8");
            
            //设置上传单个文件最大值(1 M)
            upload.setFileSizeMax(1024*1024);
    
            //设置总共可以上传文件的大小
            upload.setSizeMax(1024*1024*10);
    
            return upload;
        }
        public String upLoadParseRequest(ServletFileUpload upload,javax.servlet.http.HttpServletRequest request,String uploadPath) throws IOException, FileUploadException {
            String msg = "";
            //将前端请求解析,封装成一个FileItem对象
            List<FileItem> fileItems = upload.parseRequest(request);
            for (FileItem fileItem : fileItems) {
                //判断是否为普通的表单
                if (fileItem.isFormField()){
                    //普通表单
                    String name = fileItem.getFieldName();
                    String value = fileItem.getString("UTF-8");
                    System.out.println(name+":"+value);
                }else{
    
                    //==================================处理文件=================================
                    //拿到文件名
                    String uploadFileName = fileItem.getName();
                    System.out.println("上传的文件名:"+uploadFileName);
                    //判断文件名是否存在
                    if (uploadFileName.trim().equals("")||uploadFileName==null){
                        continue;
                    }
                    //获得真的文件名(去掉多余的路径)
                    String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
                    //得到文件后缀名
                    String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
    
                    //文件后缀不符合,直接return,不处理
                    System.out.println("文件信息[ 文件名:"+fileName+"----文件类型:"+fileExtName+"]");
    
                    //使用UUID(唯一识别通用码),保证文件名唯一
                    String uuidPath = UUID.randomUUID().toString();
    
                    //=====================================文件处理完毕========================================
    
                    //=====================================存放地址处理========================================
                    //文件真实存在的路径
                    String realPath = uploadPath+"/"+uuidPath;
                    //创建对应文件夹
                    File realPathFile = new File(realPath);
                    if (!realPathFile.exists()){
                        realPathFile.mkdir();
                    }
                    //====================================存放地址处理完毕=====================================
    
                    //获得文件上传流
                    InputStream inputStream = fileItem.getInputStream();
    
                    //创建文件输出流
                    FileOutputStream fos = new FileOutputStream(realPath+"/"+fileName);
    
                    //创建缓冲区
                    byte[] buffer = new byte[1024*8];
    
                    //判断是否读取完毕
                    int len = 0;
                    //如果大于0,说明还存在数据
                    while ((len = inputStream.read(buffer))>0){
                        fos.write(buffer,0,len);
                    }
    
                    fos.close();
                    inputStream.close();
    
                    msg = "文件上传成功";
                    //清除临时文件
                    //fileItem.delete();
                }
    
            }
    
            return msg;
        }
    }
    
    
  • 上传成功跳转页面

    
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
        <style>
    
            body{
                background-color: moccasin;
            }
            p{
                align-content: center;
                font-size:40px;
                color: lightcoral;
            }
    
        </style>
    </head>
    <body>
    
    <p>${msg}</p>
    
    </body>
    </html>
    
    
  • 配置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>UploadServlet</servlet-name>
            <servlet-class>priv.sehun.servlet.UploadServlet</servlet-class>
        </servlet>
        
        <servlet-mapping>
            <servlet-name>UploadServlet</servlet-name>
            <url-pattern>/upload</url-pattern>
        </servlet-mapping>
    </web-app>
    
  • 运行结果展示
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

  • 3
    点赞
  • 2
    评论
  • 5
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

苹果和狗

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值