为您推荐:
精华内容
最热下载
问答
  • 5星
    2.73MB weixin_44573410 2021-02-21 15:00:38
  • 5星
    83.82MB weixin_40228600 2021-04-30 14:12:58
  • 5星
    5.16MB weixin_46831482 2021-09-14 15:57:03
  • 5星
    1.51MB weixin_40228600 2021-05-05 11:03:25
  • 5星
    16.2MB weixin_45750628 2021-01-14 22:14:27
  • 5星
    171.06MB qq_41934573 2021-05-12 22:33:50
  • 5星
    84.69MB weixin_40228600 2021-06-09 10:12:21
  • 5星
    73.72MB weixin_40228600 2021-05-23 13:40:54
  • 5星
    34.38MB weixin_40228600 2021-04-11 22:00:07
  • 5星
    1.18MB weixin_40228600 2021-03-29 18:19:33
  • 16KB a1265262132 2018-06-20 22:25:43
  • 5星
    875KB weixin_39260028 2018-07-11 15:39:57
  • 214KB qq_22237579 2017-12-25 15:04:50
  • 文章目录1、文件上传准备2、Fileltem类3、ServletFileUpload类 1、文件上传准备 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的。 一般选择采用apache的开源工具common-fileupload这个...

    1、文件上传准备

    在这里插入图片描述

    1. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的。
    2. 一般选择采用apache的开源工具common-fileupload这个文件上传组件。
    3. common-fileupload是依赖于common-lo这个包的,所以还需要下载这个包。
    4. 文件下载地址:
      https://mvnrepository.com/artifact/commons-io/commons-io
      https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload
    5. 创建项目流程:
      IDEA中建个空项目,在其中new一个模块file
      采用apache的开源工具common-fileupload文件上传组件
      common-fileupload依赖于commin-io这个jar包
      直接去Maven仓库搜索、下载即可!
      模块中新建lib目录,把两个包复制过去,右键add as Library即可~
      [注意:使用IDEA导包需要注意修复路径,将lib添加到项目输出目录]
    6. 实用类介绍及面试问题(重点)
      优化文件上传的四个方法:
      在这里插入图片描述

    2、Fileltem类

    在HTML页面input必须有name<input type="file" name="filename">
    表单如果包含一个文件上传输入项的话,这个表单的enctype属性就必须设置为multipart/form-data

    	<%--  通过表单上传文件
          get:上传文件大小有限制
          post:上传文件大小没有限制
          --%>
      <form action="" enctype="multipart/form-data" method="post">
        上传用户: <input type="text" name="username"><br/>
        <p><input type="file" name="file1"></p>
        <p><input type="file" name="file2"></p>
        <p><input type="submit"> | <input type="reset"></p>
      </form>
    

    浏览器表单的类型如果为multipart/form-data ,在服务器端想获取数据就要通过流。

    3、ServletFileUpload类

    ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个Fileltem对象中。使用其parseRequest(HttpServletRequest)方法可以将通过表单中每一个HTML标签提交的数据封装成一个Fileltem对象,然后以L ist列表的形式返回。使用该方法处理上传文件简单易用。

    编写代码:

    <!--pom.xml-->
        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.10.0</version>
        </dependency>
    
    
    <!--web.xml-->
    <!--注册文件上传的servlet-->
    <servlet>
        <servlet-name>FileServlet</servlet-name>
        <servlet-class>com.xiao.servlet.FileServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FileServlet</servlet-name>
        <url-pattern>/upload.do</url-pattern>
    </servlet-mapping>
    
    

    4、编码

    info.jsp

    <%@ page language="java" contentType="text/html;charset=UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
        <title>Insert title here</title>
    </head>
    <body>
    
    <%=request.getAttribute("msg")%>
    
    </body>
    </html>
    
    

    index.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>$Title$</title>
      </head>
      <body>
    
    <%--  通过表单上传文件
          get:上传文件大小有限制
          post:上传文件大小没有限制
          --%>
    <%--${pageContext.request.contextPath}获取服务器路径--%>
      <form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
        上传用户: <input type="text" name="username"><br/>
        <p><input type="file" name="file1"></p>
        <p><input type="file" name="file2"></p>
        <p><input type="submit"> | <input type="reset"></p>
      </form>
    
      </body>
    </html>
    
    

    FileServlet

    package com.kuang.servlet;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    import java.util.UUID;
    
    import javax.servlet.ServletException;
    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.FileUploadException;
    import org.apache.commons.fileupload.ProgressListener;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    
    /**
     * Servlet implementation class FileSerlvet
     */
    public class FileServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        /**
         * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
         *      response)
         */
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // TODO Auto-generated method stub
            // response.getWriter().append("Served at: ").append(request.getContextPath());
    
            // 判断上传的文件普通表单还是带文件的表单
            if (!ServletFileUpload.isMultipartContent(request)) {
                return;//终止方法运行,说明这是一个普通的表单,直接返回
            }
            //创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访间上传的文件;
            String uploadPath =this.getServletContext().getRealPath("/WEB-INF/upload");
            File uploadFile = new File(uploadPath);
            if (!uploadFile.exists()){
                uploadFile.mkdir(); //创建这个月录
            }
    
            // 创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件
            String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
            File file = new File(tmpPath);
            if (!file.exists()) {
                file.mkdir();//创建临时目录
            }
    
            // 处理上传的文件,一般都需要通过流来获取,我们可以使用 request, getInputstream(),原生态的文件上传流获取,十分麻烦
            // 但是我们都建议使用 Apache的文件上传组件来实现, common-fileupload,它需要旅 commons-io组件;
            try {
                // 创建DiskFileItemFactory对象,处理文件路径或者大小限制
                DiskFileItemFactory factory = getDiskFileItemFactory(file);
                /*
                 * //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件 factory.setSizeThreshold(1024 *
                 * 1024); //缓存区大小为1M factory.setRepository (file);//临时目录的保存目录,需要一个File
                 */
    
                // 2、获取ServletFileUpload
                ServletFileUpload upload = getServletFileUpload(factory);
    
                // 3、处理上传文件
                // 把前端请求解析,封装成FileItem对象,需要从ServletFileUpload对象中获取
                String msg = uploadParseRequest(upload, request, uploadPath);
    
                // Servlet请求转发消息
                System.out.println(msg);
                if(msg == "文件上传成功!") {
                    // Servlet请求转发消息
                    request.setAttribute("msg",msg);
                    request.getRequestDispatcher("info.jsp").forward(request, response);
                }else {
                    msg ="请上传文件";
                    request.setAttribute("msg",msg);
                    request.getRequestDispatcher("info.jsp").forward(request, response);
                }
    
            } catch (FileUploadException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
        }
    
        public static DiskFileItemFactory getDiskFileItemFactory(File file) {
            DiskFileItemFactory factory = new DiskFileItemFactory();
            // 通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中;
            factory.setSizeThreshold(1024 * 1024);// 缓冲区大小为1M
            factory.setRepository(file);// 临时目录的保存目录,需要一个file
            return factory;
        }
    
        public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
            ServletFileUpload upload = new ServletFileUpload(factory);
            // 监听长传进度
            upload.setProgressListener(new ProgressListener() {
    
                // pBYtesRead:已读取到的文件大小
                // pContextLength:文件大小
                public void update(long pBytesRead, long pContentLength, int pItems) {
                    System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead);
                }
            });
    
            // 处理乱码问题
            upload.setHeaderEncoding("UTF-8");
            // 设置单个文件的最大值
            upload.setFileSizeMax(1024 * 1024 * 10);
            // 设置总共能够上传文件的大小
            // 1024 = 1kb * 1024 = 1M * 10 = 10м
    
            return upload;
        }
    
        public static String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request, String uploadPath)
                throws FileUploadException, IOException {
    
            String msg = "";
    
            // 把前端请求解析,封装成FileItem对象
            List<FileItem> fileItems = upload.parseRequest(request);
            for (FileItem fileItem : fileItems) {
                if (fileItem.isFormField()) {// 判断上传的文件是普通的表单还是带文件的表单
                    // getFieldName指的是前端表单控件的name;
                    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;
                    }
    
                    // 获得上传的文件名/images/girl/paojie.png
                    String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
                    // 获得文件的后缀名
                    String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
    
                    /*
                     * 如果文件后缀名fileExtName不是我们所需要的 就直按return.不处理,告诉用户文件类型不对。
                     */
    
                    System.out.println("文件信息[件名: " + fileName + " ---文件类型" + fileExtName + "]");
                    // 可以使用UID(唯一识别的通用码),保证文件名唯
                    // 0UID. randomUUID(),随机生一个唯一识别的通用码;
                    String uuidPath = UUID.randomUUID().toString();
    
                    // ================处理文件完毕==============
    
                    // 存到哪? uploadPath
                    // 文件真实存在的路径realPath
                    String realPath = uploadPath + "/" + uuidPath;
                    // 给每个文件创建一个对应的文件夹
                    File realPathFile = new File(realPath);
                    if (!realPathFile.exists()) {
                        realPathFile.mkdir();
                    }
                    // ==============存放地址完毕==============
    
    
                    // 获得文件上传的流
                    InputStream inputStream = fileItem.getInputStream();
                    // 创建一个文件输出流
                    // realPath =真实的文件夹;
                    // 差了一个文件;加上翰出文件的名产"/"+uuidFileName
                    FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
    
                    // 创建一个缓冲区
                    byte[] buffer = new byte[1024 * 1024];
                    // 判断是否读取完毕
                    int len = 0;
                    // 如果大于0说明还存在数据;
                    while ((len = inputStream.read(buffer)) > 0) {
                        fos.write(buffer, 0, len);
                    }
                    // 关闭流
                    fos.close();
                    inputStream.close();
    
                    msg = "文件上传成功!";
                    fileItem.delete(); // 上传成功,清除临时文件
                    //=============文件传输完成=============
                }
            }
            return msg;
    
        }
    }
    
    
    

    成功截图:
    在这里插入图片描述
    文件上传后的地址在此目录下:
    在这里插入图片描述

    5、避坑

    代码运行时,TOMCAT启动不了,报了好几个错误,错误如下:
    java.lang.IllegalStateException: 启动子级时出错
    Artifact smbms-next:war exploded: Artifact is being deployed, please wait...
    Caused by: java.lang.NoClassDefFoundError: org/apache/commons/fileupload/FileItemFactory
    javax.management.RuntimeOperationsException: 调用方法[manageApp]时发生异常等等

    搜寻的解决方案基本上都是:
    1.所需的包没有导进项目里
    在这里插入图片描述
    2.web.xml里url-pattern里少了一个 / 在这里插入图片描述
    3. 以上方法我都试过没有效果,最终的解决方法是把所需导入包放进WEB-INF目录的lib里
    在这里插入图片描述
    之前我的lib不是在WEB-INF里,秦疆老师的lib也没有放在WEB-INF里,是可以运行的。
    所以具体原因我也不太清楚,大致是包没导进项目里。
    主要注意第二种解决方法,解决方法仅供参考。

    展开全文
    qq_45344691 2021-10-07 16:41:33
  • 198KB feiqipengcheng 2020-05-25 22:26:39
  • 267KB weixin_38640150 2020-09-02 03:02:40
  • 1.81MB qqyouhappy 2016-06-23 19:55:31
  • 78KB weixin_38624914 2020-09-02 03:01:22
  • JavaWeb实现文件上传,超详细

    JavaWeb文件上传

    Hello,各位小伙伴好久不见,本周我们学习JavaWeb中最重要的技术之一,文件上传,该案例我会用一个小型的用户管理系统实现,一步步带入,内容通俗易懂,下面我们步入正题!

    做一个简单的用户管理系统

    功能如下

    用户注册,参数有用户名,用户名密码,用户头像,

    用户登录,登录成功后跳转至主页显示用户头像和名称,支持注销账号,注销账号后,页面跳转至登录页

    技术栈:后端采用JavaWebMySQL5.7Druid连接池、前端采用bootstrap框架结合jsp

    先上效果

    完整操作项目演示:

    包含:用户注册,用户登录,用户登录后显示用户信息,即头像,账号名,最右侧显示注销,点击注销后跳转至登录页

    在这里插入图片描述

    在这里插入图片描述

    项目结构

    Java源码

    在这里插入图片描述

    前端页面jsp

    在这里插入图片描述

    准备工作

    数据表准备

    t_user_info

    CREATE TABLE `t_user_info` (
      `noid` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL,
      `password` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL,
      `head_portrait_path` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
      PRIMARY KEY (`noid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    
    

    Jar文件准备

    项目所需jar包如下

    在这里插入图片描述

    jar文件放在WEB-INF/lib文件夹下,主要是为了安全。

    文件上传需要的jar包:

    在这里插入图片描述

    jar文件我会同步资源,小伙伴们不用担心哦~

    项目结构简介

    本项目采用三层架构实现,即:service层、dao层、servlet层

    1. servlet层:

      由于之前的servlet层类增删改查的类太过于多,导致代码冗余,所以在jsp页面发送请求时,采用模块化的方式进行访问,例如:

      http://localhost/Blog/user/addUser 访问user模块的addUser

      http://localhost/Blog/user/getUserList 访问user模块的getUserList

      http://localhost/Blog/dept/addDept 访问dept的addDept

      http://localhost/Blog/dept/getDeptList 访问dept的getDeptList

      这样一个对应的类解决该类的所有对数据库的增删改查操作,提高了程序的可维护性,减少代码的冗余,提高了程序的健壮性。

      抽取出公共父类:BaseServlet

    BaseServlet类核心代码

    public class BaseServlet extends HttpServlet{
    
    	@Override
    	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		//1.获取浏览器请求的资源
    		String uri = req.getRequestURI();
    		//2.获取请求的方法名,最后斜线后面的内容
    		String methodName = uri.substring(uri.lastIndexOf("/")+1);
    		try {
    			//3.根据方法名获取方法,通过反射获取
    			Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
    			//4.调用方法
    			method.invoke(this, req, resp);
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    
    
    1. dao层

      dao层抽取出公共数据库连接类,BaseDao,基于db.properties配置文件连接本地数据库

    db.properties配置文件:

    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql://127.0.0.1/db_blog?useSSL=true
    username=root
    password=111111
    

    BaseDao核心代码

    public class BaseDao {
    
    	//采用单例模式实现,防止数据库连接超时
    	private static DataSource ds = null;
    	
    	public QueryRunner initQueryRunner() throws Exception {
    		if (ds == null) {
    			String dbFile = this.getClass().getClassLoader().getResource("/").getFile();
    			dbFile = dbFile.substring(1) + "db.properties";
    			
    			FileReader fr = new FileReader(dbFile);
    			
    			Properties pro = new Properties();
    			pro.load(fr);
    			
    			ds = DruidDataSourceFactory.createDataSource(pro);
    		}
    		QueryRunner qur = new QueryRunner(ds);
    		return qur;
    	}
    }
    
    

    Userservlet核心代码

    @WebServlet("/user/*")
    public class UserServlet extends BaseServlet{
    
    	//业务层类,用于调用业务层方法
    	UserService userService = new UserServiceImpl();
    	
    	/**
    	 * 注册用户
    	 * @param req
    	 * @param resp
    	 */
    	public void register(HttpServletRequest req, HttpServletResponse resp) {
    		//获取数据
    		DiskFileItemFactory factory = new DiskFileItemFactory();
    		ServletFileUpload fileUpload  = new ServletFileUpload(factory);
    		try {
    			List<FileItem> fileItemList = fileUpload.parseRequest(req);
    			//获取当前项目的路径
    			String classesPath = this.getClass().getResource("/").getPath();
    			
    			File f1 = new File(classesPath);
    			//项目路径
    			String projectPath = f1.getParentFile().getParentFile().getParentFile().getAbsolutePath();
    			
    			//最后上传的路径
    			String uploadPath = projectPath + "\\ROOT\\upload\\";
    			
    			File f2 = new File(uploadPath);
    			if (!f2.exists()) {
    				f2.mkdirs();
    			}
    			//存入数据库的路径
    			String headPortraitPath = "";
    			for (FileItem fileItem : fileItemList) {
    				if (!fileItem.isFormField()) {
    					//是文件域
    					String fileName = fileItem.getName();
    					//获取原来文件的后缀
    					String suffix = fileName.substring(fileName.lastIndexOf("."));
    					//生成新的文件名,为防止重复,采用随机数
    					String destFileName = UUID.randomUUID().toString().replace("-", "");
    					
    					//存入数据库的路径拼接完毕,例如格式:随机文件名.txt
    					headPortraitPath = destFileName + suffix;
    					//写入硬盘的路径
    					uploadPath += headPortraitPath;
    					//获取输入流
    					InputStream is = fileItem.getInputStream();
    					//输出流
    					FileOutputStream fos = new FileOutputStream(uploadPath);
    					//将上传的文件写入指定路径
    					try {
    						byte[] buf = new byte[10240];
    						while (true) {
    							int realLen = is.read(buf, 0, buf.length);
    							if (realLen < 0) {
    								break;
    							}
    							fos.write(buf, 0, realLen);
    						}
    					} finally {
    						if (fos != null)
    							fos.close();
    						if (is != null)
    							is.close();
    					}
    				} else {
    					//不是文件域,是普通控件
    					//获取输入框的名称
    					String fieldName = fileItem.getFieldName();
    					//获取输入框中的值
    					String fieldVal = fileItem.getString("utf-8");
    					//加入请求域中
    					req.setAttribute(fieldName, fieldVal);
    				}
    			}
    			String username = (String) req.getAttribute("username");
    			String password = (String) req.getAttribute("password");
    			//验证参数是否合法,不为空
    			boolean flag = userService.exam(username, password);
    			if (flag) {
    				//将数据存入数据库
    				User user = new User();
    				user.setUsername(username);
    				user.setPassword(password);
    				user.setHead_portrait_path(headPortraitPath);
    				if (userService.save(user)) {
    					resp.sendRedirect(req.getContextPath()+"/login.jsp");
    				}
    			} else {
    				resp.sendRedirect(req.getContextPath()+"/register.jsp");
    			}
    		} catch (Exception e1) {
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    		}
    	}
    	
    	/**
    	 * 用户登录
    	 * @param req
    	 * @param resp
    	 */
    	public void login(HttpServletRequest req, HttpServletResponse resp) {
    		//获取数据
    		String username = req.getParameter("username");
    		String password = req.getParameter("password");
    		//验证是否存在该用户
    		User user = new User();
    		try {
    			if (userService.exam(username, password)) {
    				user.setUsername(username);
    				user.setPassword(password);
    				user = userService.getByUser(user);
    				if (user.getHead_portrait_path() != null) {
    					HttpSession s1 = req.getSession();
    					s1.setAttribute("user", user);
    					resp.sendRedirect(req.getContextPath()+"/index.jsp");
    				} else {
    					resp.sendRedirect(req.getContextPath()+"/login.jsp");
    				}
    			} else {
    				resp.sendRedirect(req.getContextPath()+"/login.jsp");
    			}
    		} catch(Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    }
    
    

    博主絮语

    千言万语不舍,但美好的时光总是短暂的,博主本周分享就到此结束了,本周博客主题:文件上传

    制作不易,博主愿与各位前辈大佬共学习,共前进,编程之路任重道远,艰辛,我们共前进,克服难关,挺过去,就是彩虹,风雨过后就是彩虹,加油,愿我们成为想要成为的人!

    都看到这里了,不确定来个一键三连么~

    我们下周见~

    展开全文
    weixin_45526437 2021-08-21 19:04:06
  • 315KB weixin_38607311 2020-09-02 02:42:05
  • 1.84MB zgsdzczh 2017-08-16 09:11:31
  • 214KB qq_32902741 2017-06-10 22:51:30
  • .JavaWeb文件上传1.自定义上传文件上传时的表单设计要符合文件提交的方式:1.提交方式:post2.表单中有文件上传的表单项:3.指定表单类型:文件上传类型:enctype=“multipart/form-data”`jsp上传页面:Created by ...

    .JavaWeb文件上传

    1.自定义上传

    文件上传时的表单设计要符合文件提交的方式:

    1.提交方式:post

    2.表单中有文件上传的表单项:

    3.指定表单类型:文件上传类型:enctype=“multipart/form-data”`

    jsp上传页面:

    Created by IntelliJ IDEA.

    User: cenyu

    Date: 16-12-20

    Time: 下午8:52

    To change this template use File | Settings | File Templates.

    --%>

    文件上传

    用户名:

    文件:

    Servlet处理程序:

    package test;

    import javax.servlet.ServletException;

    import javax.servlet.ServletInputStream;

    import javax.servlet.annotation.WebServlet;

    import javax.servlet.http.HttpServlet;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    import java.io.BufferedReader;

    import java.io.IOException;

    import java.io.InputStreamReader;

    /**

    * 手动处理文件上传

    * Created by cenyu on 16-12-20.

    */

    @WebServlet("/upload")

    public class uploadServlet extends HttpServlet {

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

    this.doGet(request,response);

    }

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

    /*

    request.getQueryString();//获取GET:username=Tom&pwd=888

    request.getInputStream();//获取POST:inputStream

    request.getParameter("");//使用这个可以不区分get和post

    */

    //获取表单(POST)数据

    ServletInputStream in = request.getInputStream();//此方法得到所有的提交信息,不仅仅只有内容

    //转换流

    InputStreamReader inReaser = new InputStreamReader(in);

    //缓冲流

    BufferedReader reader = new BufferedReader(inReaser);

    String str = null;

    while ((str=reader.readLine()) != null){

    System.out.println(str);

    }

    }

    }

    提交测试文件:

    aaaaaaaaa

    bbbbbbbbb

    ccccccccc

    dddddddd

    运行结果:

    -----------------------------468783950766433362585077246

    Content-Disposition: form-data; name="username"

    cenyu

    -----------------------------468783950766433362585077246

    Content-Disposition: form-data; name="file1"; filename="test.txt"

    Content-Type: text/plain

    aaaaaaaaa

    bbbbbbbbb

    ccccccccc

    dddddddd

    -----------------------------468783950766433362585077246--

    2.FileUpload组件

    FileUpload组件,也叫文件上传组件,是Apache提供的开源项目

    组件使用方法:

    1.下载,引入jar文件

    引入commons-fileupload-1.2.1.jar

    引入依赖包commons-io-1.4.jar

    3.Api学习

    文件上传组件API

    FileItemFactory 文件上传工厂类(把每一个请求表单项封装为一个个FileItem对象)

    fac.setRepository(repository);设置上传临时目录

    ServletFileUpload 文件上传核心类,可以获取所有的FileItem对象

    list pload.parseRequest(request);

    Boolean isMultipartContent(request);判断表单类型,文件上传表单但会true

    upload.setFileSizeMax(fileSizeMax);设置单个上传文件的最大值

    upload.setSizeMax(sizeMax);设置总上传文件大总的最大值

    upload.setHeaderEcoding("UTF-8");设置上传文件名的编码

    FileItem 封装了普通表单项的值以及文件上传表单元素的值

    item.getFiledName();获取上传表单元素的名称

    item.getString();获取上传数据;

    item.getString("UTF-8");获取上传数据,处理中文

    item.getContentType();获取上传文件类型[文件上传项]

    item.getInputStream();获取文件流[文件上传项]

    item.getName();获取文件名[文件上传项]

    item.write(file);把数据写到file文件

    item.delete();删除临时文件

    使用FileUpload组件来写上传方法的整体代码:

    需求:

    1.设置单个文件不能超过30M

    2.设置总大小不能超过50M

    3.上传目录,上传到项目资源目录下的upload目录

    4.上传文件不能覆盖,解决上传文件名的同名问题

    前端jsp页面中的代码没有改变,只需要看FileUploadServlet中的代码:

    package 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.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.InputStream;

    import java.nio.file.attribute.FileTime;

    import java.util.List;

    import java.util.UUID;

    /**

    * 文件上传组件完整使用

    * Created by cenyu on 16-12-20.

    */

    @WebServlet("/load")

    public class FileUploadServlet extends HttpServlet {

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

    this.doGet(request,response);

    }

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

    //1.创建文件上传工厂类

    DiskFileItemFactory fac = new DiskFileItemFactory();

    //2.创建文件上传核心类对象

    ServletFileUpload upload = new ServletFileUpload(fac);

    //【一、设置单个文件最大30M】

    upload.setFileSizeMax(30*1024*1024);//30M

    //【二、设置总文件大小:50M】

    upload.setSizeMax(50*1024*1024); //50M

    //判断,当前表单是否为文件上传表单

    if (upload.isMultipartContent(request)){

    try {

    //3.把请求数据转换为FileItem对象的集合

    List list = upload.parseRequest(request);

    //遍历,得到每一个上传项

    for (FileItem item : list){

    //判断:是普通表单项,还是文件上传表单项

    if (item.isFormField()){

    //普通表单x

    String fieldName = item.getFieldName();//获取元素名称

    String value = item.getString("UTF-8"); //获取元素值

    System.out.println(fieldName+" : "+value);

    }else {

    //文件上传表单

    String name = item.getName(); //上传的文件名称

    /**

    * 【四、文件重名】

    * 对于不同的用户的test.txt文件,不希望覆盖,

    * 后台处理:给用户添加一个唯一标记!

    */

    //a.随机生成一个唯一标记

    String id = UUID.randomUUID().toString();

    //与文件名拼接

    name = id + name;

    //【三、上传到指定目录:获取上传目录路径】

    String realPath = getServletContext().getRealPath("/upload");

    //创建文件对象

    File file = new File(realPath, name);

    item.write(file);

    item.delete();

    }

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    }else {

    System.out.println("不处理!");

    }

    }

    }

    展开全文
    weixin_31574149 2021-02-26 15:26:18
  • javaWeb文件上传与下载 理论(原理分析): 文件下载 要获取下载文件的路径 下载的文件名(显示给客户端的文件名) 设置想办法让浏览器能够支持下载我们需要的东西(attachment;filename) 创建文件输入流 创建缓冲区...

    javaWeb文件上传与下载

    理论(原理分析):

    文件下载

    1. 要获取下载文件的路径
    2. 下载的文件名(显示给客户端的文件名)
    3. 设置想办法让浏览器能够支持下载我们需要的东西(attachment;filename
    4. 创建文件输入流
    5. 创建缓冲区
    6. 获取OutputStream对象
    7. FileOutputStream流写入到buffer缓冲区
    8. 使用OutputStream将缓冲区中的数据输出到客户端!
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 要获取下载文件的路径
        String realPath = "F:\\班级管理\\西开【19525】\\2、代码\\JavaWeb\\javaweb-02-servlet\\response\\target\\classes\\秦疆.png";
        System.out.println("下载文件的路径:"+realPath);
        // 2. 下载的文件名是啥?
        String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
        // 3. 设置想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西,中文文件名URLEncoder.encode编码,否则有可能乱码
        resp.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));
        // 4. 获取下载文件的输入流
        FileInputStream in = new FileInputStream(realPath);
        // 5. 创建缓冲区
        int len = 0;
        byte[] buffer = new byte[1024];
        // 6. 获取OutputStream对象
        ServletOutputStream out = resp.getOutputStream();
        // 7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端!
        while ((len=in.read(buffer))>0){
            out.write(buffer,0,len);
        }
    
        in.close();
        out.close();
    }
    

    注意:设置头时attachment;filename的分号如果不小心写成冒号,则只会显示图片而不是下载图片

    文件上传

    需要的依赖包

    1. commons.io

      <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
      <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
          <version>2.11.0</version>
      </dependency>
      
    2. commons.fileupload(依赖于``commons.io`)

      <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
      <dependency>
          <groupId>commons-fileupload</groupId>
          <artifactId>commons-fileupload</artifactId>
          <version>1.4</version>
      </dependency>
      

    需要用到的类

    ServletFileUpload 负责处理上传文件数据,并将表单每个输入项封装成一个FileItem`对象,在使用`ServletFileUplead`对象解析请求时需要`DiskFileItemFactory`对象。所以我们需要在进行解析工作前构造好`DiskFileItemFactory`对象,通过`ServletFileUpload`对象的构造方法或`setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性

    FileItem

    在HTML页面input必须要有name<input type="file" name="filename">

    表单如果包含一个文件上传输入项的话,这个表单的enctype属性就必须设置为multipart/form-data

    <form action="" enctype="multipart/form-data" method="post">
    
        上传用户<input type="text" name="username"><br/>
    
        <p><input type="file" name="file1"></p>
        <p><input type="file" name="file2"></p>
    
        <p><input type="submit"> | <input type="reset"></p>
    
    </form>
    

    常用方法

    //isFormField方法用于判断FileItem类地下封装的数据是一个普通文本表单
    //还是一个文件表单,如果是普通表单字段则返回true,否则返回false
    boolean isFormField();
    
    //getFiledName()方法用于返回表单标签name属性的值。
    String getFieldName();
    //getString()方法用于将FileItem对象中保存的数据流内容以一个字符串返回
    String getString();
    
    //getName()方法用于获得文件上传字段中的文件名
    String getName();
    
    //以流的形式返回上传文件的数据内容。
    InputStream getInputStream();
    
    //delete方法用来清空FileItem类对象中存放的主体内容
    //如果主体内容被保存在临时文件中,delete方法将删除该临时文件。
    void delete();
    

    ServletFileUpload

    ServletFileUpload负责处理上传的文件数据,并架构表单中每个输入项封装成一个FileItem对象中,使用其**parseRequest(HttpServletRequest r)**方法可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回。使用该方法处理上传文件简单易用。

    package com.example.file;
    
    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 javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    import java.util.UUID;
    
    @WebServlet(name = "FileServlet", value = "/FileServlet")
    public class FileServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
            //判断上传的文件时普通表单还是带文件的表单
            if (!ServletFileUpload.isMultipartContent(request)) {
                return;//终止方法运行,说明这是个普通表单,直接返回
            }
            //创建上传文件的保存路径 建议保存到WEB-INF路径下 安全 用户无法直接访问上传的文件
            String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
            File uploadFile = new File(uploadPath);
            if (!uploadFile.exists()) {
                uploadFile.mkdir();//创建这个目录
            }
            //缓存,临时文件
            String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
            File tmpFile = new File(tmpPath);
            if (!tmpFile.exists()) {
                tmpFile.mkdir();//创建这个临时目录
            }
            //处理上传的文件
            /*
            ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象
            在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象
            所以 Wimbledon需要在进行解析工作前构造好DiskFileItemFactory对象
            通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性
             */
    
            DiskFileItemFactory factory = getDiskFileItemFactory(tmpFile);
            ServletFileUpload servletFileUpload = getServletFileUpload(factory);
            String result = extracted(request, uploadPath, servletFileUpload);
            request.setAttribute("result",result);
            System.out.println(result);
            request.getRequestDispatcher("info.jsp").forward(request,response);
    
    
    
        }
    
        private String extracted(HttpServletRequest request, String uploadPath, ServletFileUpload servletFileUpload){
            StringBuilder msg = new StringBuilder();
            try{
                //3.处理上传的文件
                //吧前端请求解析 封装成一个FileItem对象
                List<FileItem> fileItems = servletFileUpload.parseRequest(request);
                for (FileItem fileItem : fileItems) {
                    String name;
                    if(fileItem.isFormField()){
                        //getFileName指的是前端表单控件Name
                        name = fileItem.getFieldName();
                        String value = fileItem.getString("UTF-8");//处理乱码
                        System.out.println(name+":"+value);
                    }else {//文件
                        //----------------处理文件-----------------//
                        //获取文件全名
                        name = fileItem.getName();
                        //判断文件大小
                        if(fileItem.getSize() >= 1024 * 1024 * 10){
                            msg.append(name).append(":").append("超过内存限制,拒绝传输<br>");
                            fileItem.delete();//上传成功,清除临时文件
                            continue;
                        }
                        //可能存在文件名不合法的情况
                        if(name == null|| name.trim().equals("")){
                            fileItem.delete();//上传成功,清除临时文件
                            continue;
                        }
                        //获取上传的文件名
                        String fileName = name.substring(name.lastIndexOf('/') + 1);
                        //获取文件后缀
                        String fileExtName = name.substring(name.lastIndexOf('.') + 1);
                    /*
                         如果后缀名不是需要的则直接return不处理
                         告诉用户文件类型不正确
                     */
    
                        //可以使用UUID(唯一识别的通识码)保证文件名唯一
                        //UUID.randomUUID(),随机产生一个识别的通用码
    
                        //网络传输中的东西都需要序列化
                        //实体类,如果想要在多个计算机上运行,需要传输(把对象都序列化)
                        //implement Serializable : 标记接口,JVM---> Java栈  本地方法栈 native -->C++
                        String uuidPath = UUID.randomUUID().toString();
    
    
                        //----------------存放地址-----------------//
                        //存放位置 uploadPath
                        //文件真是存在的路径 realPath
                        String realPath = uploadPath +"/"+uuidPath;
                        //给每个文件创建一个对应的文件夹
                        File realPathFile = new File(realPath);
                        if(!realPathFile.exists()){
                            realPathFile.mkdir();
                        }
    
    
                        //----------------文件传输-----------------//
                        //获得文件上传的流
                        InputStream is = fileItem.getInputStream();
    
                        //创建一个文件输出流
                        FileOutputStream fos = new FileOutputStream(realPath + "/" + name);
    
                        //创建一个缓冲区
                        byte[] buffer = new byte[1024 * 1024];
    
                        //判断是否读取完毕
                        int len =0;
                        //如果大于0说明还存在数据
                        while ((len=is.read(buffer))>0){
                            fos.write(buffer,0,len);
                        }
    
                        //关闭流
                        fos.close();
                        is.close();
    
                        msg.append(name).append(":上传成功<br>");
    
                        fileItem.delete();//上传成功,清除临时文件
                    }
                }
    
            }catch (Exception e){
                e.printStackTrace();
                return "上传异常";
            }
    
            return msg.toString();
        }
    
        private ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
            //2.获取ServletFileUpload
            ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
            //监听文件上传进度
    //        servletFileUpload.setProgressListener((l, all, i) -> System.out.println("总大小:" + all + "\t已上传:" + l));
            //处理乱码问题
            servletFileUpload.setHeaderEncoding("UTF-8");
            //设置单个文件的最大值
    //        servletFileUpload.setFileSizeMax(1024 * 1024 * 10);//10M
            //设置总共能够上传文件的大小
    //        servletFileUpload.setSizeMax(1024 * 1024 * 10 * 2);
            /*
                如果设置了大小则如果出现超过大小的情况 则直接异常
             */
            return servletFileUpload;
        }
    
        private DiskFileItemFactory getDiskFileItemFactory(File dir) {
            //1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区时,将他放到临时文件中
            if(dir!=null){
                factory.setSizeThreshold(1024 * 1024);//缓存区大小为1M
                factory.setRepository(dir);
            }
            return factory;
        }
    }
    
    

    不足:

    在上述代码中并没有真正限制大小,而是允许文件上传到tmp文件夹中后再进行判断大小是否超额。目前我只能在前端进行判断大小进行限制,后端进行限制会在转换的时候异常,然而该异常又会导致request奔溃,前端收不到对应回复。

    实战(项目实战):

    项目一览:

    1. 项目目录
      在这里插入图片描述

    2. 项目展示

      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

    初始化项目

    1. 我使用的编辑器:IDEA2021.2

    2. 项目创建

      在这里插入图片描述
      在这里插入图片描述

    依赖注入(pom.xml)

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.example</groupId>
      <artifactId>File</artifactId>
      <version>1.0-SNAPSHOT</version>
      <name>File</name>
      <packaging>war</packaging>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
          <junit.version>5.7.1</junit.version>
          </properties>
    
      <dependencies>
                                                                            <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>4.0.1</version>
          <scope>provided</scope>
        </dependency>                                                                        
        <dependency>
          <groupId>org.junit.jupiter</groupId>
          <artifactId>junit-jupiter-api</artifactId>
          <version>${junit.version}</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>org.junit.jupiter</groupId>
          <artifactId>junit-jupiter-engine</artifactId>
          <version>${junit.version}</version>
          <scope>test</scope>
        </dependency>
          <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
          <dependency>
              <groupId>commons-io</groupId>
              <artifactId>commons-io</artifactId>
              <version>2.11.0</version>
          </dependency>
          <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
          <dependency>
              <groupId>commons-fileupload</groupId>
              <artifactId>commons-fileupload</artifactId>
              <version>1.4</version>
          </dependency>
          <!-- JSTL表达式的依赖 -->
          <dependency>
              <groupId>javax.servlet.jsp.jstl</groupId>
              <artifactId>jstl-api</artifactId>
              <version>1.2</version>
          </dependency>
          <!-- standard标签库 -->
          <dependency>
              <groupId>taglibs</groupId>
              <artifactId>standard</artifactId>
              <version>1.1.2</version>
          </dependency>
    
    
      </dependencies>
    
      <build>
         <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>3.3.1</version>
          </plugin>
         </plugins>
      </build>
    </project>
    

    编写(导入)静态资源

    1. JSP

      1. upload.jsp

        <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
        <!DOCTYPE html>
        <html>
        <head>
          <title>文件上传</title>
          <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/css/css.css"/>
          <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/css/css2.css"/>
        </head>
        <body>
        
        <div class="form">
        
          <form id="fileForm" action="${pageContext.request.contextPath}/UploadServlet" enctype="multipart/form-data" method="post">
        
            上传用户<input type="text" name="username"><br>
            <br>
            <div>
              <label for="files">选择文件上传(可多选)</label>
              <input type="file" id="files" name="files" multiple="" style="opacity: 0;">
            </div>
            <br>
            <div class="preview">
              <p>当前还没有选中的文件</p>
            </div>
            <br>
            <p>
              <input id="submitBtn" type="button" value="上传"> | <input type="reset" id="resetBtn">
            </p>
          </form>
              <a href="${pageContext.request.contextPath }/DownloadServlet?method=getFileNameList"><button>去下载文件</button></a>
        </div>
        
        </body>
        
        <script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.8.3.min.js"></script>
        <script type="text/javascript" src="${pageContext.request.contextPath }/js/upload.js"></script>
        
        </html>
        
      2. info.jsp

        <%@ page contentType="text/html;charset=UTF-8" language="java" %>
        <html>
        <head>
            <title>上传文件</title>
            <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/css/css.css"/>
            <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/css/css2.css"/>
        </head>
        <body>
        
        <div class="form">
            <h2>上传状态:</h2>
            <div>${result}</div>
            <a href="${pageContext.request.contextPath }/upload.jsp"><button>去上传文件</button></a>
            <a href="${pageContext.request.contextPath }/DownloadServlet?method=getFileNameList"><button>去下载文件</button></a>
        </div>
        
        </body>
        
        </html>
        
      3. download.jsp

        <%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8"%>
        <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
        <!DOCTYPE HTML>
        <html>
        <head>
            <title>下载文件</title>
            <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/css/css.css"/>
            <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/css/css2.css"/>
        </head>
        
        <body>
        
        <div class="form">
            <!-- 遍历Map集合 -->
            <c:forEach var="me" items="${fileNameMap}">
                <c:url value="/DownloadServlet" var="downurl">
                    <c:param name="path" value="${me.key}"></c:param>
                    <c:param name="realName" value="${me.value}"></c:param>
                </c:url>
                <a href="${downurl}&method=downloadFile">[下载]</a>-----<a href="${downurl}&method=previewFile">[预览]</a>${me.value}<br/>
            </c:forEach>
            <a href="${pageContext.request.contextPath }/upload.jsp"><button>去上传文件</button></a>
        </div>
        
        </body>
        </html>
        
    2. CSS

      • css.css

        
        html {
            font-family: sans-serif;
        }
        
        .form {
            width: 580px;
            background: #ccc;
            margin: 0 auto;
            padding: 20px;
            border: 1px solid black;
        }
        
        form ol {
            padding-left: 0;
        }
        
        form li, div > p {
            background: #eee;
            display: flex;
            justify-content: space-between;
            margin-bottom: 10px;
            list-style-type: none;
            border: 1px solid black;
        }
        
        form img {
            height: 64px;
            order: 1;
        }
        
        form p {
            line-height: 32px;
            padding-left: 10px;
        }
        
        form label, form button {
            background-color: #7F9CCB;
            padding: 5px 10px;
            border-radius: 5px;
            border: 1px ridge black;
            font-size: 0.8rem;
            height: auto;
        }
        
        form label:hover, form button:hover {
            background-color: #2D5BA3;
            color: white;
        }
        
        form label:active, form button:active {
            background-color: #0D3F8F;
            color: white;
        }
        
      • css2.css

        body {
            padding: 0;
            margin: 0;
        }
        
        svg:not(:root) {
            display: block;
        }
        
        .playable-code {
            background-color: #f4f7f8;
            border: none;
            border-left: 6px solid #558abb;
            border-width: medium medium medium 6px;
            color: #4d4e53;
            height: 100px;
            width: 90%;
            padding: 10px 10px 0;
        }
        
        .playable-canvas {
            border: 1px solid #4d4e53;
            border-radius: 2px;
        }
        
        .playable-buttons {
            text-align: right;
            width: 90%;
            padding: 5px 10px 5px 26px;
        }
        
        
    3. JavaScript

      • jquery-1.8.3.min.js 这个我就不写进来了,可以到网上下载

      • upload.js

        const inputFiles = document.getElementById('files');
        const preview = document.querySelector('.preview');
        const submitBtn = $("#submitBtn");
        const resetBtn = $("#resetBtn");
        const fileForm = $("#fileForm");
        const maxSize = 1024*1024*10;//10M 单个文件大小限制
        
        inputFiles.style.opacity = 0;
        inputFiles.addEventListener('change', updateImageDisplay);
        
        //可以显示的图片类型
        const fileTypes = [
            'image/jpeg',
            'image/pjpeg',
            'image/png'
        ];
        
        function validFileType(file) {
            return fileTypes.includes(file.type);
        }
        
        function returnFileSize(number) {
            if(number < 1024) {
                return number + 'bytes';
            } else if(number >= 1024 && number < 1048576) {
                return (number/1024).toFixed(1) + 'KB';
            } else if(number >= 1048576) {
                return (number/1048576).toFixed(1) + 'MB';
            }
        }
        
        
        function updateImageDisplay() {
            let isOK = true;
        
            while(preview.firstChild) {
                preview.removeChild(preview.firstChild);
            }
        
            const curFiles = inputFiles.files;
            if(curFiles.length === 0) {
                const para = document.createElement('p');
                para.textContent = '当前还没有选中的文件';
                preview.appendChild(para);
                isOK = false;
            } else {
                const list = document.createElement('ol');
                preview.appendChild(list);
        
                for(const file of curFiles) {
                    const listItem = document.createElement('li');
                    const para = document.createElement('p');
                    para.textContent = "文件名称: "+file.name+", 文件大小: "+returnFileSize(file.size);
        
                    //根据文件大小判断是否超过限制
                    if(file.size >= maxSize){
                        para.style.color = "red";
                        isOK = false;
                    }else {
                        para.style.color = "green";
                    }
        
                    //如果是图片类型就显示图片
                    if(validFileType(file)) {
                        const image = document.createElement('img');
                        image.src = URL.createObjectURL(file);
                        listItem.appendChild(image);
                    }
        
                    listItem.appendChild(para);
        
                    list.appendChild(listItem);
                }
        
            }
            return isOK;
        }
        
        submitBtn.bind("click",function () {
            if(updateImageDisplay()){
                if(confirm("您确定要将这些文件上传吗?")){
                    fileForm.submit();
                }else {
                    alert("未选中文件或者选中的文件不符合上传要求!");
                }
            }
        })
        
        resetBtn.bind("click",function () {
            setTimeout(updateImageDisplay,200);
        })
        

    编写Servlet

    web.xml

    这里没有写Servlet的映射,直接由Servlet中的@WebServlet(name = "---", value = "/---")注释搞定映射。于是只在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">
    
        <!--设置欢迎页面-->
        <welcome-file-list>
            <welcome-file>upload.jsp</welcome-file>
        </welcome-file-list>
    
    </web-app>
    

    UploadServlet

    package com.example.file;
    
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    import java.util.UUID;
    
    @WebServlet(name = "UploadServlet", value = "/UploadServlet")
    public class UploadServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
            //判断上传的文件时普通表单还是带文件的表单
            if (!ServletFileUpload.isMultipartContent(request)) {
                return;//终止方法运行,说明这是个普通表单,直接返回
            }
            //创建上传文件的保存路径 建议保存到WEB-INF路径下 安全 用户无法直接访问上传的文件
            String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
            File uploadFile = new File(uploadPath);
            if (!uploadFile.exists()) {
                uploadFile.mkdir();//创建这个目录
            }
            //缓存,临时文件
            String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
            File tmpFile = new File(tmpPath);
            if (!tmpFile.exists()) {
                tmpFile.mkdir();//创建这个临时目录
            }
            //处理上传的文件
            /*
            ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象
            在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象
            所以 Wimbledon需要在进行解析工作前构造好DiskFileItemFactory对象
            通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性
             */
    
            DiskFileItemFactory factory = getDiskFileItemFactory(tmpFile);
            ServletFileUpload servletFileUpload = getServletFileUpload(factory);
            String result = extracted(request, uploadPath, servletFileUpload);
            request.setAttribute("result",result);
            System.out.println(result);
            request.getRequestDispatcher("info.jsp").forward(request,response);
    
    
    
        }
    
        private String extracted(HttpServletRequest request, String uploadPath, ServletFileUpload servletFileUpload){
            StringBuilder msg = new StringBuilder();
            try{
                //3.处理上传的文件
                //吧前端请求解析 封装成一个FileItem对象
                List<FileItem> fileItems = servletFileUpload.parseRequest(request);
                for (FileItem fileItem : fileItems) {
                    String name;
                    if(fileItem.isFormField()){
                        //getFileName指的是前端表单控件Name
                        name = fileItem.getFieldName();
                        String value = fileItem.getString("UTF-8");//处理乱码
                        System.out.println(name+":"+value);
                    }else {//文件
                        //----------------处理文件-----------------//
                        //获取文件全名
                        name = fileItem.getName();
                        //判断文件大小
                        if(fileItem.getSize() >= 1024 * 1024 * 10){
                            msg.append(name).append(":").append("超过内存限制,拒绝传输<br>");
                            fileItem.delete();//上传成功,清除临时文件
                            continue;
                        }
                        //可能存在文件名不合法的情况
                        if(name == null|| name.trim().equals("")){
                            fileItem.delete();//上传成功,清除临时文件
                            continue;
                        }
                        //获取上传的文件名
                        String fileName = name.substring(name.lastIndexOf('/') + 1);
                        //获取文件后缀
                        String fileExtName = name.substring(name.lastIndexOf('.') + 1);
                    /*
                         如果后缀名不是需要的则直接return不处理
                         告诉用户文件类型不正确
                     */
    
                        //可以使用UUID(唯一识别的通识码)保证文件名唯一
                        //UUID.randomUUID(),随机产生一个识别的通用码
    
                        //网络传输中的东西都需要序列化
                        //实体类,如果想要在多个计算机上运行,需要传输(把对象都序列化)
                        //implement Serializable : 标记接口,JVM---> Java栈  本地方法栈 native -->C++
                        String uuidPath = UUID.randomUUID().toString();
    
    
                        //----------------存放地址-----------------//
                        //存放位置 uploadPath
                        //文件真实存在的路径 realPath = uploadPath/uuid_fileName
                        String realPath = uploadPath + "/" +uuidPath + "_" + name;
                        System.out.println(realPath);
    
    
                        //----------------文件传输-----------------//
                        //获得文件上传的流
                        InputStream is = fileItem.getInputStream();
    
                        //创建一个文件输出流
                        FileOutputStream fos = new FileOutputStream(realPath);
    
                        //创建一个缓冲区
                        byte[] buffer = new byte[1024 * 1024];
    
                        //判断是否读取完毕
                        int len =0;
                        //如果大于0说明还存在数据
                        while ((len=is.read(buffer))>0){
                            fos.write(buffer,0,len);
                        }
    
                        //关闭流
                        fos.close();
                        is.close();
    
                        msg.append(name).append(":上传成功<br>");
    
                        fileItem.delete();//上传成功,清除临时文件
                    }
                }
    
            }catch (Exception e){
                e.printStackTrace();
                return "上传异常";
            }
    
            return msg.toString();
        }
    
        private ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
            //2.获取ServletFileUpload
            ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
            //监听文件上传进度
    //        servletFileUpload.setProgressListener((l, all, i) -> System.out.println("总大小:" + all + "\t已上传:" + l));
            //处理乱码问题
            servletFileUpload.setHeaderEncoding("UTF-8");
            //设置单个文件的最大值
    //        servletFileUpload.setFileSizeMax(1024 * 1024 * 10);//10M
            //设置总共能够上传文件的大小
    //        servletFileUpload.setSizeMax(1024 * 1024 * 10 * 2);
            /*
                如果设置了大小则如果出现超过大小的情况 则直接异常
             */
            return servletFileUpload;
        }
    
        private DiskFileItemFactory getDiskFileItemFactory(File dir) {
            //1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区时,将他放到临时文件中
            if(dir!=null){
                factory.setSizeThreshold(1024 * 1024);//缓存区大小为1M
                factory.setRepository(dir);
            }
            return factory;
        }
    }
    

    DownloadServlet

    package com.example.file;
    
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    import java.util.UUID;
    
    @WebServlet(name = "UploadServlet", value = "/UploadServlet")
    public class UploadServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
            //判断上传的文件时普通表单还是带文件的表单
            if (!ServletFileUpload.isMultipartContent(request)) {
                return;//终止方法运行,说明这是个普通表单,直接返回
            }
            //创建上传文件的保存路径 建议保存到WEB-INF路径下 安全 用户无法直接访问上传的文件
            String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
            File uploadFile = new File(uploadPath);
            if (!uploadFile.exists()) {
                uploadFile.mkdir();//创建这个目录
            }
            //缓存,临时文件
            String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
            File tmpFile = new File(tmpPath);
            if (!tmpFile.exists()) {
                tmpFile.mkdir();//创建这个临时目录
            }
            //处理上传的文件
            /*
            ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象
            在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象
            所以 Wimbledon需要在进行解析工作前构造好DiskFileItemFactory对象
            通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性
             */
    
            DiskFileItemFactory factory = getDiskFileItemFactory(tmpFile);
            ServletFileUpload servletFileUpload = getServletFileUpload(factory);
            String result = extracted(request, uploadPath, servletFileUpload);
            request.setAttribute("result",result);
            System.out.println(result);
            request.getRequestDispatcher("info.jsp").forward(request,response);
    
    
    
        }
    
        private String extracted(HttpServletRequest request, String uploadPath, ServletFileUpload servletFileUpload){
            StringBuilder msg = new StringBuilder();
            try{
                //3.处理上传的文件
                //吧前端请求解析 封装成一个FileItem对象
                List<FileItem> fileItems = servletFileUpload.parseRequest(request);
                for (FileItem fileItem : fileItems) {
                    String name;
                    if(fileItem.isFormField()){
                        //getFileName指的是前端表单控件Name
                        name = fileItem.getFieldName();
                        String value = fileItem.getString("UTF-8");//处理乱码
                        System.out.println(name+":"+value);
                    }else {//文件
                        //----------------处理文件-----------------//
                        //获取文件全名
                        name = fileItem.getName();
                        //判断文件大小
                        if(fileItem.getSize() >= 1024 * 1024 * 10){
                            msg.append(name).append(":").append("超过内存限制,拒绝传输<br>");
                            fileItem.delete();//上传成功,清除临时文件
                            continue;
                        }
                        //可能存在文件名不合法的情况
                        if(name == null|| name.trim().equals("")){
                            fileItem.delete();//上传成功,清除临时文件
                            continue;
                        }
                        //获取上传的文件名
                        String fileName = name.substring(name.lastIndexOf('/') + 1);
                        //获取文件后缀
                        String fileExtName = name.substring(name.lastIndexOf('.') + 1);
                    /*
                         如果后缀名不是需要的则直接return不处理
                         告诉用户文件类型不正确
                     */
    
                        //可以使用UUID(唯一识别的通识码)保证文件名唯一
                        //UUID.randomUUID(),随机产生一个识别的通用码
    
                        //网络传输中的东西都需要序列化
                        //实体类,如果想要在多个计算机上运行,需要传输(把对象都序列化)
                        //implement Serializable : 标记接口,JVM---> Java栈  本地方法栈 native -->C++
                        String uuidPath = UUID.randomUUID().toString();
    
    
                        //----------------存放地址-----------------//
                        //存放位置 uploadPath
                        //文件真实存在的路径 realPath = uploadPath/uuid_fileName
                        String realPath = uploadPath + "/" +uuidPath + "_" + name;
                        System.out.println(realPath);
    
    
                        //----------------文件传输-----------------//
                        //获得文件上传的流
                        InputStream is = fileItem.getInputStream();
    
                        //创建一个文件输出流
                        FileOutputStream fos = new FileOutputStream(realPath);
    
                        //创建一个缓冲区
                        byte[] buffer = new byte[1024 * 1024];
    
                        //判断是否读取完毕
                        int len =0;
                        //如果大于0说明还存在数据
                        while ((len=is.read(buffer))>0){
                            fos.write(buffer,0,len);
                        }
    
                        //关闭流
                        fos.close();
                        is.close();
    
                        msg.append(name).append(":上传成功<br>");
    
                        fileItem.delete();//上传成功,清除临时文件
                    }
                }
    
            }catch (Exception e){
                e.printStackTrace();
                return "上传异常";
            }
    
            return msg.toString();
        }
    
        private ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
            //2.获取ServletFileUpload
            ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
            //监听文件上传进度
    //        servletFileUpload.setProgressListener((l, all, i) -> System.out.println("总大小:" + all + "\t已上传:" + l));
            //处理乱码问题
            servletFileUpload.setHeaderEncoding("UTF-8");
            //设置单个文件的最大值
    //        servletFileUpload.setFileSizeMax(1024 * 1024 * 10);//10M
            //设置总共能够上传文件的大小
    //        servletFileUpload.setSizeMax(1024 * 1024 * 10 * 2);
            /*
                如果设置了大小则如果出现超过大小的情况 则直接异常
             */
            return servletFileUpload;
        }
    
        private DiskFileItemFactory getDiskFileItemFactory(File dir) {
            //1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区时,将他放到临时文件中
            if(dir!=null){
                factory.setSizeThreshold(1024 * 1024);//缓存区大小为1M
                factory.setRepository(dir);
            }
            return factory;
        }
    }
    

    迷糊与疑问

    1. 当我给ServletFileUpload设置了大小限制时,如果前端传入的文件超过了限制会出现异常,不是普通的异常,它会导致request直接坏掉,后续进行转发与重定向时都不能得到想要的效果,参考网上博客(捕捉异常 在catch块中转发、重定向)依然无法解决问题。

    参考与致谢

    oad servletFileUpload = new ServletFileUpload(factory);
    //监听文件上传进度
    // servletFileUpload.setProgressListener((l, all, i) -> System.out.println(“总大小:” + all + “\t已上传:” + l));
    //处理乱码问题
    servletFileUpload.setHeaderEncoding(“UTF-8”);
    //设置单个文件的最大值
    // servletFileUpload.setFileSizeMax(1024 * 1024 * 10);//10M
    //设置总共能够上传文件的大小
    // servletFileUpload.setSizeMax(1024 * 1024 * 10 * 2);
    /*
    如果设置了大小则如果出现超过大小的情况 则直接异常
    */
    return servletFileUpload;
    }

    private DiskFileItemFactory getDiskFileItemFactory(File dir) {
        //1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区时,将他放到临时文件中
        if(dir!=null){
            factory.setSizeThreshold(1024 * 1024);//缓存区大小为1M
            factory.setRepository(dir);
        }
        return factory;
    }
    

    }

    
    ### 迷糊与疑问
    
    1. 当我给ServletFileUpload设置了大小限制时,如果前端传入的文件超过了限制会出现异常,不是普通的异常,它会导致request直接**坏掉**,后续进行转发与重定向时都不能得到想要的效果,参考网上博客(捕捉异常 在catch块中转发、重定向)依然无法解决问题。
    
    ### 参考与致谢
    
    1. 感谢 B站狂神说 提供的javaweb学习视频,本文参考该视频编写
    
    展开全文
    Ctrl_kun 2021-08-19 17:55:06
  • weixin_33918202 2021-02-27 20:50:16
  • 5星
    5KB u013132051 2016-06-27 20:12:58
  • 5星
    139KB beauxie 2016-09-18 20:10:09
  • weixin_54883831 2021-07-30 13:29:30
  • weixin_32564229 2021-02-28 19:36:55
  • 86KB weixin_38532849 2020-08-30 16:56:04
  • weixin_31100517 2021-03-07 09:32:05
  • weixin_29865183 2021-02-12 17:53:45
  • m0_46392290 2021-01-24 16:42:41
  • 75KB weixin_38504687 2020-09-02 22:15:05
  • weixin_33954881 2021-04-12 14:24:46
  • weixin_47287832 2021-08-27 23:43:39

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 17,342
精华内容 6,936
关键字:

javaweb文件上传

java 订阅