Java实现文件上传详解

您所在的位置:网站首页 在线文件传输java Java实现文件上传详解

Java实现文件上传详解

2023-08-06 01:06| 来源: 网络整理| 查看: 265

文件上传的原理

在这里插入图片描述 你如果要去一个网站,如果发一个请求或文件下载,

电脑为客户端, 服务器为s端,服务器中有网站,web应用,还有文件操作系统File System

IO流,两个池子或许穿东西需要一条管道,两台不同电脑之间的管道就是网络

网络中存在协议,协议就是为了传东西的

传输文件需要响应头和响应体,想要传输文件或者下载文件咱们也要设置固定的响应头和响应体

上传文件首先让浏览器能够支持文件上传 input(file)

input file 通过网络上传到web应用,再从web应用传到文件系统

http 80

https 443

URL:指向互联网上的一个具体的地址

NetWork网络传输如何写?

写网络传输 工程十分浩大,所以我们直接用现有的java类

文件上传的注意事项 为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名(-时间戳 -uuid -md5 -位运算)要限制上传文件的最大值可以限制上传文件的类型,在收到上传文件名时,判断后缀是否合法 上传文件需要用到的类

需要用到的类

ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象,在使用

ServletFileUpload对象解析请求时需要DiskFileItemFactory对象。所以,我们需要在进行解析工作前构造好

DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象

的fileItemFactory属性

ServletFileUpload类

ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象中,使用其parseRequest(HttpServletRequest)方法

可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回,使用该方法处理上传文件简单易用 trim()方法去掉首尾空格

实现过程

前端提交form表导致FileServlet中 在这里插入图片描述

我们在FileServlet中实现上传文件的功能 1.首先 判断上传的文件是普通表单还是带文件的表单

if(!ServletFileUpload.isMultipartContent(request)){ return;//终止方法运行,说明这是一个普通的表单,直接返回 }

2.创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件

String uploadPath=this.getServletContext().getRealPath("/WEB-INF/upload"); File uploadFile=new File(uploadPath); if(!uploadFile.exists()){ uploadFile.mkdir();//创建这个目录 } System.out.println("创建目录成功");

3.缓存,临时文件:文件超过规定大小,被弄成临时文件,过几天自动删除,或者提醒用户转存为永久

String tmpPath=this.getServletContext().getRealPath("/WEB-INF/upload"); File file=new File(tmpPath); if(!file.exists()){ file.mkdir();//创建这个目录 }

4.处理上传的文件,一般需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦 但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于commons-io组件: 🌟创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的: DiskFileItemFactory factory=new DiskFileItemFactory(); 通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中: factory.setSizeThreshold(1024*1024); actory.setRepository(file);

DiskFileItemFactory factory=getDiskFileItemFactory(file); //====================================================== DiskFileItemFactory getDiskFileItemFactory(File file){ DiskFileItemFactory factory=new DiskFileItemFactory(); //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中: factory.setSizeThreshold(1024*1024); factory.setRepository(file); return factory; }

5.获取ServletFileload 用来监听 监听文件的上传进度

ServletFileUpload upload=getServletFileUpload(factory); //===================================================== ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){ ServletFileUpload upload=new ServletFileUpload(factory); //🌟监听文件上传的进度 upload.setProgressListener(new ProgressListener() { @Override //pBytesRead:已读取到的文件大小 //pContentLength:文件大小 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=10M upload.setSizeMax(1024*1024*10); return upload; }

6.处理上传文件

String msg=uploadParseRequest(upload,request,uploadPath); //======================================================= String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request,String uploadPath){ String msg="上传失败"; try { List fileItems=upload.parseRequest(request); //fileItem每一个表单对象 for (FileItem fileItem : fileItems) { //判断上传的文件是普通的表单还是带文件的表单 if(fileItem.isFormField()){ //getFiledName指的是前端表单控件的name; String name=fileItem.getFieldName(); String value=fileItem.getString("UTF-8"); System.out.println(name+":"+value); }else{ //如果是文件表单 //1.处理文件================= String uploadFileName=fileItem.getName(); System.out.println("上传的文件名:"+uploadFileName); //可能存在文件名不合法的情况 if(uploadFileName.trim().equals("")||uploadFileName==null){ continue; } //获得上传的文件名 /images/gurl/paojie.png String fileName=uploadFileName.substring(uploadFileName.lastIndexOf("/")+1); //获得文件的后缀名 String fileExtName=uploadFileName.substring(uploadFileName.lastIndexOf(".")+1); /* * 如果文件的后缀名fileExtName不是我们所要的 * 就直接return 不处理,告诉用户文件类型不对 * */ //可以使用UUID(唯一识别的通用码),保证文件名唯一 //UUID.randomUUID() 随机生成一个唯一识别的通用码 //网络传输中的东西都需要序列化, //POJO,实体类只能在本机上用,如果想要在多个电脑上运行,传输===》需要把对象都序列化了 //implements Serializable 没有方法的接口-》标记接口。JVM虚拟机在运行的时候,JVM的本地方法栈-- native->c++ //JNI=java Native Interface->java 本地化接口 //Java栈 //UUID 通过位运算,生成随机序列号保证不重复性 String uuidPath = UUID.randomUUID().toString(); //2.存放地址================= //存到哪?uploadPath //文件真实存在的路径realPath String realPath=uploadPath+"/"+uuidPath; //给每个文件创建一个对应的文件夹 File realPathFile=new File(realPath); if(!realPathFile.exists()){ realPathFile.mkdir(); } //3.文件传输================= //获取文件上传的流 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); } msg="上传文件成功"; //关闭流 fos.close(); inputStream.close(); fileItem.delete();//上传文件成功,清除临时文件 } } } catch (FileUploadException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return msg; }

7.最后得到文件上传的结果利用Servlet请求转发

//servlet请求转发消息 request.setAttribute("msg",msg); request.getRequestDispatcher("info.jsp").forward(request,response); 完整代码 package com.lding.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 javax.servlet.http.HttpServletRequest; import java.io.*; import java.util.List; import java.util.UUID; /** * @program: FileTransport * @description: ${description} * @author: 王丁 * @date: 2021-11-11 11:25 **/ public class FileServlet extends javax.servlet.http.HttpServlet { protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { System.out.println("进入FileServlet"); //判断上传的文件是普通表单还是带文件的表单 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();//创建这个目录 } System.out.println("创建目录成功"); //缓存,临时文件 //文件超过规定大小,被弄成临时文件,过几天自动删除,或者提醒用户转存为永久 String tmpPath=this.getServletContext().getRealPath("/WEB-INF/upload"); File file=new File(tmpPath); if(!file.exists()){ file.mkdir();//创建这个目录 } //处理上传的文件,一般需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦 //但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于commons-io组件: /* ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileTtem对象 在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象 所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象 通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象 对象的fileItemFactory属性 */ DiskFileItemFactory factory=getDiskFileItemFactory(file); // //🌟监听文件上传的进度 ServletFileUpload upload=getServletFileUpload(factory); //3.🌟处理上传文件 String msg=uploadParseRequest(upload,request,uploadPath); //servlet请求转发消息 request.setAttribute("msg",msg); request.getRequestDispatcher("info.jsp").forward(request,response); } DiskFileItemFactory getDiskFileItemFactory(File file){ DiskFileItemFactory factory=new DiskFileItemFactory(); //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中: factory.setSizeThreshold(1024*1024); factory.setRepository(file); return factory; } ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){ ServletFileUpload upload=new ServletFileUpload(factory); //🌟监听文件上传的进度 upload.setProgressListener(new ProgressListener() { @Override //pBytesRead:已读取到的文件大小 //pContentLength:文件大小 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=10M upload.setSizeMax(1024*1024*10); return upload; } String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request,String uploadPath){ String msg="上传失败"; try { List fileItems=upload.parseRequest(request); //fileItem每一个表单对象 for (FileItem fileItem : fileItems) { //判断上传的文件是普通的表单还是带文件的表单 if(fileItem.isFormField()){ //getFiledName指的是前端表单控件的name; String name=fileItem.getFieldName(); String value=fileItem.getString("UTF-8"); System.out.println(name+":"+value); }else{ //如果是文件表单 //1.处理文件================= String uploadFileName=fileItem.getName(); System.out.println("上传的文件名:"+uploadFileName); //可能存在文件名不合法的情况 if(uploadFileName.trim().equals("")||uploadFileName==null){ continue; } //获得上传的文件名 /images/gurl/paojie.png String fileName=uploadFileName.substring(uploadFileName.lastIndexOf("/")+1); //获得文件的后缀名 String fileExtName=uploadFileName.substring(uploadFileName.lastIndexOf(".")+1); /* * 如果文件的后缀名fileExtName不是我们所要的 * 就直接return 不处理,告诉用户文件类型不对 * */ //可以使用UUID(唯一识别的通用码),保证文件名唯一 //UUID.randomUUID() 随机生成一个唯一识别的通用码 //网络传输中的东西都需要序列化, //POJO,实体类只能在本机上用,如果想要在多个电脑上运行,传输===》需要把对象都序列化了 //implements Serializable 没有方法的接口-》标记接口。JVM虚拟机在运行的时候,JVM的本地方法栈-- native->c++ //JNI=java Native Interface->java 本地化接口 //Java栈 //UUID 通过位运算,生成随机序列号保证不重复性 String uuidPath = UUID.randomUUID().toString(); //2.存放地址================= //存到哪?uploadPath //文件真实存在的路径realPath String realPath=uploadPath+"/"+uuidPath; //给每个文件创建一个对应的文件夹 File realPathFile=new File(realPath); if(!realPathFile.exists()){ realPathFile.mkdir(); } //3.文件传输================= //获取文件上传的流 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); } msg="上传文件成功"; //关闭流 fos.close(); inputStream.close(); fileItem.delete();//上传文件成功,清除临时文件 } } } catch (FileUploadException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return msg; } protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { } } 运行结果

在这里插入图片描述

如果对您有帮助,免费的赞点一个~感谢🙏


【本文地址】


今日新闻


推荐新闻


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