JavaWeb:文件上传(详)

您所在的位置:网站首页 文件上传的实现 JavaWeb:文件上传(详)

JavaWeb:文件上传(详)

2023-07-18 12:43| 来源: 网络整理| 查看: 265

文件上传 一、注意事项 为保证服务器安全,上传文件应当保存在外界无法直接访问的路径(如 WEB-INF 目录下) 为防止文件覆盖,要为上传的文件生成一个唯一的文件名(如-时间戳,-uuid,-md5,-位运算算法) 要限制上传文件的大小的最大值。 可以限制上传文件的类型,在获取上传文件名时,判断后缀名是否合法。 二、文件上传 1、组件

浏览器处理上传文件,是将文件以流的形式提交到服务器端。

commons-fileupload:Apache 的文件上传组件,取代原生的文件上传流。 commons-io:commons-fileupload 组件依赖于该组件。 2、前端表单

form 表单

提交方式:method=“post”(post传送的数据量大,可视为不受限制) 编码类型:enctype="multipart/form-data"(表单包含文件上传控件时必须使用) enctype 属性 application/x-www=form-urlencoded:默认方式,只处理表单域中的 value 属性值,将表单域中的值处理成 URL 编码方式; multipart/form-data:以二进制流的方式处理表单数据,除了表单域中的 value 属性值,还会处理表单域的文件内容,将其封装到请求参数中,不会对字符编码; text/plain:将空格转换为+号,其它字符不做编码处理,适用于通过表单发送邮件。

input 输入框

类型:type=“file”

属性:要求具有 name 属性

3、实用类介绍

注:

一个表单项(即一个字段)会被解析为一个 FileItem 对象; 也就是说,一个 FileItem 对象封装了一个表单项。

DiskFileItemFactory 类

设置临时文件夹; 设置文件缓存区大小。 // 1、设置临时文件夹 void setRepository(File repository) // *2、设置文件缓存区大小 void setSizeThreshold(int sizeThreshold)

ServletFileUpload 类

判断表单是否包含文件上传控件:即是否设置了enctype="multipart/form-data"; 设置 FileItemFactory 属性; 解析前端请求:将表单项解析成 FileItem 对象; *监听文件上传进度、处理乱码问题、设置文件上传最大值 // 1、静态方法:判断表单是否包含文件上传控件,负责处理文件数据 static boolean isMultipartContent(HttpServletRequest request) // 2、父类方法:设置FileItemFactory属性,也可通过构造方法设置 void setFileItemFactory(FileItemFactory factory) // 3、解析前端请求,将每个表单项解析并封装成FileItem对象,以List列表的形式返回。 List parseRequest(HttpServletRequest request) // *4、父类方法:监听文件上传进度 void setProgressListener(ProgressListener pListener) // *5、父类方法:处理乱码问题 void setHeaderEncoding(String encoding) // *6、父类方法:设置单个文件的最大值 void setFileSizeMax(long fileSizeMax) // *7、父类方法:设置总共能够上传的文件大小 void setSizeMax(long sizeMax)

DiskFileItem:FileItem 接口实现类

判断表单项是否上传文件,即类型是否为type=“file”; 获取字段名; 获取数据流内容; 获取上传文件名; 获取上传文件输入流; 清空 FileItem 对象。 // 1、判断表单项是否为上传文件:普通文本返回true,否则返回false boolean isFormField(); // 2、获取字段名:表单项name属性的值 String getFieldName(); // 3、FileItem对象中保存的数据流内容:即表单项为普通文本的输入值 String getString(); // 4、获取表单项为文件上传的文件名 String getName(); // 5、获取上传文件的输入流 InputStream getInputStream(); // 6、清空FileItem类对象中存放的主体内容,如果主体内容被保存在临时文件中,delete方法将删除该临时文件 void delete(); 4、实现步骤

带 * 号的是用于完善业务的辅助功能,不是必要的。

判断表单:是否包含文件上传控件。 创建上传文件和临时文件的保存路径。 创建 DiskFileItemFactory 对象。 设置临时文件夹 *设置缓冲区大小 创建 ServletFileUpload 对象 设置 FileItemFactory *监听文件上传进度、处理乱码问题、设置单个文件和总共上传文件的最大值 解析请求并处理文件传输 解析前端请求,将每个表单项解析并封装成 FileItem 对象 判断表单项是否为上传文件 处理普通文本: 获取字段名 获取数据流内容 处理文件: 获取上传文件名 生成随机 UUID 作为文件存储路径,并为其生成文件夹 通过 IO 流传输文件 三、代码实现 1、导入Maven依赖

(普通项目则导入jar包)

commons-fileupload commons-fileupload 1.3.3 2、前端页面

fileUpload.jsp

上传用户:

|

success.jsp

${msg} 3、Servlet public class FileServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 判断表单是否包含文件上传控件 if (!ServletFileUpload.isMultipartContent(req)) { // 不包含文件上传控件,即普通表单 return; } // 创建上传文件的保存路径:外界无法直接访问 String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload"); File uploadFile = new File(uploadPath); makeDirIfNotExist(uploadFile); // 创建临时文件的保存路径 String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp"); File tmpFile = new File(tmpPath); makeDirIfNotExist(tmpFile); // 1、创建DiskFileItemFactory对象 DiskFileItemFactory factory = getDiskFileItemFactory(tmpFile); // 2、创建ServletFileUpload对象 ServletFileUpload servletFileUpload = getServletFileUpload(factory); // 3、解析请求并处理文件传输 String msg = ""; try { msg = uploadParseRequest(req, servletFileUpload, uploadPath); } catch (FileUploadException e) { e.printStackTrace(); } req.setAttribute("msg", msg); req.getRequestDispatcher("/success.jsp").forward(req, resp); } private String uploadParseRequest(HttpServletRequest httpServletRequest, ServletFileUpload servletFileUpload, String uploadPath) throws FileUploadException, IOException { String msg = ""; // 解析前端请求,将每个表单项解析并封装成FileItem对象 List fileItems = servletFileUpload.parseRequest(httpServletRequest); for (FileItem fileItem : fileItems) { // 判断表单项是否为上传文件 if (fileItem.isFormField()) { // 普通文本 String filedName = fileItem.getFieldName(); // 获取字段名:表单项name属性的值 String value = fileItem.getString("UTF-8"); // FileItem对象中保存的数据流内容:即表单项为普通文本的输入值 System.out.println(filedName + ":" + value); } else { // 上传文件 // ------------------------1、处理文件------------------------ String uploadFileName = fileItem.getName();// 上传文件名 System.out.println("上传的文件名:" + uploadFileName); if (uploadFileName == null || uploadFileName.trim().equals("")) { // 文件名为空值或空 continue; // 进入下一轮循环,判断下一个FileItem对象 } String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1); // 文件后缀名 System.out.println("文件信息【文件名:" + uploadFileName + ",文件类型:" + fileExtName + "】"); // 使用UUID保证文件名唯一 String uuidPath = UUID.randomUUID().toString(); // ------------------------2、处理路径------------------------ // 存储路径:uploadPath String realPath = uploadPath + '/' + uuidPath; // 真实存在的路径 // 给每个文件创建一个文件夹 File realPathFile = new File(realPath); makeDirIfNotExist(realPathFile); // ------------------------3、文件传输------------------------ // 获得输入流 InputStream is = fileItem.getInputStream(); // 获得输出流 FileOutputStream fos = new FileOutputStream(realPathFile + "/" + uploadFileName); // 创建缓冲区 byte[] buffer = new byte[1024]; int len; while ((len = is.read(buffer)) > 0) { fos.write(buffer, 0, len); } msg = "文件上传成功!"; fileItem.delete(); // 上传成功,清除临时文件 fos.close(); is.close(); } } return msg; } private ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) { // ServletFileUpload servletFileUpload = new ServletFileUpload(factory); // 构造方法设置FileItemFactory ServletFileUpload servletFileUpload = new ServletFileUpload(); servletFileUpload.setFileItemFactory(factory); // 设置FileItemFactory // ------------------------辅助功能------------------------ // 监听文件上传进度 servletFileUpload.setProgressListener(new ProgressListener() { /** * * @param pBytesRead 已读取的文件大小 * @param pContentLength 文件大小 * @param pItems */ @Override public void update(long pBytesRead, long pContentLength, int pItems) { String percentage = (int) (((double) pBytesRead / pContentLength) * 100) + "%"; System.out.println("总大小:" + pContentLength + ",已上传:" + pBytesRead + "\t" + percentage); } }); // 处理乱码问题 servletFileUpload.setHeaderEncoding("UTF-8"); // 设置单个上传文件的最大值 servletFileUpload.setFileSizeMax(1024 * 1024 * 10); // 10M // 设置总共上传文件的最大值 servletFileUpload.setSizeMax(1024 * 1024 * 10); // 10M return servletFileUpload; } /** * 获得磁盘文件项目工程,设置缓冲文件夹及缓冲区大小 * * @param tmpFile 缓冲文件夹 * @return */ private DiskFileItemFactory getDiskFileItemFactory(File tmpFile) { // return new DiskFileItemFactory(1024 * 1024, tmpFile); DiskFileItemFactory factory = new DiskFileItemFactory(); // ------------------------辅助功能------------------------ factory.setSizeThreshold(1024 * 1024); // 1M(缓冲区大小):上传文件大于缓冲区大小时,fileupload组件将使用临时文件缓存上传文件 factory.setRepository(tmpFile); // 临时文件夹 return factory; } /** * 如果文件目录不存在,为其创建目录 * * @param file */ private void makeDirIfNotExist(File file) { if (!file.exists()) { file.mkdir(); } } } 4、注册Servlet FileServlet indi.jaywee.file.FileServlet FileServlet /upload.do 5、运行结果

上传的文件会保存在 Target 目录下对应项目的保存路径下。

非临时文件:

保存在 upload 文件夹下。 文件格式和文件名与上传文件完全相同。 每个文件存储在一个子文件夹中,文件夹名是随机生成的 UUID。

临时文件:

保存在 upload 文件夹下,同时在tmp文件夹下生成一个临时文件。 upload 文件夹下的文件:文件格式和文件名与上传文件完全相同。 tmp 文件夹下的文件:tmp 格式,文件名是随机生成的 UUID,在 Servlet 运行到 fileItem.delete() 方法时被清除。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3