javaweb--文件上传

📅 2026/7/13 3:00:37
javaweb--文件上传
JavaWeb文件上传依赖的jar包https://mvnrepository.com/artifact/commons-io/commons-io https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload注意事项为保护服务器的安全上传的文件不能直接被访问到比如放在WEB-INF目录下限制上传文件的大小限制上传文件的格式为防止上传文件名字重复导致文件被覆盖为每个文件设置一个唯一的文件名。代码解释ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象 在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象。所以我们需要在进行解析工作前构造好DiskFileItemFactory对象通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性。缓冲区和临时文件夹的重要性缓冲区的重要性防止服务器一次接收到的上传请求过多导致服务器OOM设置缓冲区的大小可以有效解决这一问题。临时文件夹的重要性在上传文件时现将上传的文件上传到临时文件夹中等待临时文件夹中的文件上传成功后再移到真正的文件目录中。好处**注意**不能单纯根据请求头中的内容进行判断文件的大小和格式等信息请求头的信息可能被篡改用户中途取消上传 / 网络中断文件只传了一半upload 文件夹残留半截损坏文件占磁盘还无法区分有效文件和残缺垃圾文件后期很难清理。文件超出大小限制代码限制单文件 10M比如用户传 20M 文件数据已经写了 10M 到 upload校验时才发现超限此时正式目录已经产生无效碎片文件。​ 3.文件后缀黑名单如禁止 exe、jsp 上传文件已经大半写入正式目录校验发现是禁止类型文件残片留在 upload存在安全风险。前端代码在HTML页面input 必须有 name表单如果包含一个文件上传输入项的话这个表单的enctype属性就必须设置为multipart/form-data浏览器表单的类型如果为multipart/form-data , 在服务器端想获取数据就要通过流。% page contentTypetext/html;charsetUTF-8 languagejava % html body form action ${pageContext.request.contextPath}/upFile.do method post enctypemultipart/form-data 上传用户input typetext nameusernamebr/ pinput typefile namefile1/p pinput typefile namefile2/p pinput typesubmit/p /form /body /html后端代码importorg.apache.commons.fileupload.FileItem;importorg.apache.commons.fileupload.FileUploadException;importorg.apache.commons.fileupload.ProgressListener;importorg.apache.commons.fileupload.disk.DiskFileItemFactory;importorg.apache.commons.fileupload.servlet.ServletFileUpload;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.File;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.InputStream;importjava.util.List;importjava.util.UUID;publicclassFileUpServletextendsHttpServlet{protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{doGet(request,response);}protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{try{//判断上传的文件是普通的表单还是带文件的表单if(!ServletFileUpload.isMultipartContent(request)){return;//如果是普通文件我们可以直接返回}//创建上传文件的保存路径建议在WEB-INF路径下安全用户无法直接访问上传的文件StringuploadPaththis.getServletContext().getRealPath(/WEB-INF/upload);FileuploadFilenewFile(uploadPath);if(!uploadFile.exists()){//如果目录不存在创建这样一个目录uploadFile.mkdir();}//临时路径假如文件超过了预期的大小我们就把他放到一个临时文件中过几天自动删除或者提醒用户转存为永久StringtmpPaththis.getServletContext().getRealPath(/WEB-INF/tmp);FiletmpFilenewFile(tmpPath);if(!tmpFile.exists()){//如果目录不存在创建这样一个目录tmpFile.mkdir();}//处理上传的文件一般都需要通过流来获取我们可以使用request.getInputStream(),原生态的文件上传流获取十分麻烦//但是我们都建议使用 Apache的文件上传组件来实现common-fileupload它需要依赖于 commons-io组件//1.创建DiskFileItemFactory对象处理文件上传路径或者大小限制的DiskFileItemFactoryfactorygetDiskFileItemFactory(tmpFile);//2.获取ServletFileUploadServletFileUploaduploadgetServletFileUpload(factory);//3.处理上传的文件StringmsguploadParseRequest(upload,request,uploadPath);//servlet请求转发消息request.setAttribute(msg,msg);request.getRequestDispatcher(upRes.jsp).forward(request,response);}catch(FileUploadExceptione){e.printStackTrace();}}publicstaticDiskFileItemFactorygetDiskFileItemFactory(FiletmpFile){DiskFileItemFactoryfactorynewDiskFileItemFactory();//通过这个工厂设置一个缓冲区当上传的文件大于这个缓冲区的时候将他放到临时文件中factory.setSizeThreshold(1024*1024);//缓存区大小为1Mfactory.setRepository(tmpFile);//临时目录的保存目录需要一个Filereturnfactory;}publicstaticServletFileUploadgetServletFileUpload(DiskFileItemFactoryfactory){ServletFileUploaduploadnewServletFileUpload(factory);//监听文件上传进度upload.setProgressListener(newProgressListener(){Override//pBytesRead:已经读取到的文件大小//pContentLength 文件大小publicvoidupdate(longpBytesRead,longpContentLength,intpItems){System.out.println(总大小pContentLength已上传pBytesRead);}});//处理乱码问题upload.setHeaderEncoding(UTF-8);//设置单个文件的最大值upload.setFileSizeMax(1024*1024*10);//设置总共能够上传文件的大小//1024 1kb * 1024 1M * 10 10Mupload.setSizeMax(1024*1024*10);returnupload;}publicstaticStringuploadParseRequest(ServletFileUploadupload,HttpServletRequestrequest,StringuploadPath)throwsFileUploadException,IOException{Stringmsg;//3.把前端请求解析封装成一个FileItem对象try{ListFileItemfileItemsupload.parseRequest(request);for(FileItemfileItem:fileItems){if(fileItem.isFormField()){//判断上传的文件是普通的表单还是带文件的表单//getFieldName指的是前端表单控件的nameStringnamefileItem.getFieldName();StringvaluefileItem.getString(UTF-8);//处理乱码System.out.println(name:value);}else{//判断它是上传的文件//处理文件////拿到文件名字StringuploadFileNamefileItem.getName();System.out.println(上传的文件名uploadFileName);if(uploadFileNamenull||uploadFileName.trim().equals()){continue;}//获得上传的文件名 /images/girl/paojie.pngStringfileNameuploadFileName.substring(uploadFileName.lastIndexOf(\\)1);//获得文件的后缀名StringfileExtNameuploadFileName.substring(uploadFileName.lastIndexOf(.)1);/* 如果文件后缀名 fileExtName 不是我们所需要的 就直接return不处理告诉用户文件类型不对。 */System.out.println(文件信息 [件名fileName---文件类型fileExtName]);//可以使用UUID唯一识别的通用码保证文件名唯一//UUID.randomUUID()随机生一个唯一识别的通用码StringuuidPathUUID.randomUUID().toString();//处理文件完毕////存到哪 uploadPath//文件真实存在的路径 realPathStringrealPathuploadPathFile.separatoruuidPath;System.out.println(文件上传的路径realPath);//给每个文件创建一个对应的文件夹FilerealPathFilenewFile(realPath);if(!realPathFile.exists()){realPathFile.mkdir();}//存放地址完毕////获得文件上传的流InputStreaminputStreamfileItem.getInputStream();//创建一个文件输出流//realPath 真实的文件夹//差了一个文件; 加上输出文件的名字/uuidFileNameFileOutputStreamfosnewFileOutputStream(realPathFile.separatorfileName);//创建一个缓冲区byte[]buffernewbyte[1024*1024];//判断是否读取完毕intlen0;//如果大于0说明还存在数据while((leninputStream.read(buffer))0){fos.write(buffer,0,len);}//关闭流fos.close();inputStream.close();msg文件上传成功;fileItem.delete();//上传成功清除临时文件//文件传输完毕//}}}catch(Exceptione){e.printStackTrace();}returnmsg;}}