Web技术基础教程 6_第1页
Web技术基础教程 6_第2页
Web技术基础教程 6_第3页
Web技术基础教程 6_第4页
Web技术基础教程 6_第5页
已阅读5页,还剩29页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

JavaWeb开发技术与案例教程第11章文件的上传与下载第11章知识结构11.1文件上传•11.1.1创建表单•11.1.2创建Servlet•11.1.3部署和运行•11.1.4多文件上传11.2文件下载•11.2.1使用超链接下载文件•11.2.2使用Servlet下载文件11.3本章小结1第11章课程导入

JavaWeb中,文件的上传与下载是Web应用程序中常见的功能之一,它允许用户在客户端与服务器之间进行文件的传输。上传功能通过HTML表单(enctype="multipart/form-data")提交文件至服务器,后端利用@MultipartConfig解析请求,将文件保存至指定路径。下载功能则通过Servlet设置响应头(Content-Disposition、Content-Type),将服务器文件流式传输至客户端。本章将学习文件上传和文件下载的使用方法。◆本章要点•掌握文件上传表单的enctype="multipart/form-data"和method="post"属性设置。•掌握使用Servlet3.0+的@MultipartConfig注解和request.getPart()方法实现文件上传。•理解文件上传中的安全注意事项,如文件大小限制和路径安全。•区分超链接下载和Servlet下载两种方式的优缺点。•掌握通过Servlet实现文件下载的核心:设置Content-Type和Content-Disposition响应头。2第11章课程导入◆素养目标•筑牢文件安全防线,防范恶意攻击:通过文件类型验证与路径遍历防护,掌握“白名单机制”在安全设计中的应用。•践行资源管理规范,保障服务稳定:在文件下载的流式输出实践中,强调“边读边写”的内存优化策略。•强化版权保护意识,尊重原创成果:在文件上传场景中,倡导对用户上传内容的版权审核。•培养全局视野,理解存储系统价值:通过分布式文件存储案例学习,建立“文件服务是系统基础设施”的认知。311.1文件上传在早期的JavaWeb开发中(使用javax.servletAPI),Servlet规范本身并不直接支持文件上传。开发者必须依赖外部库(如ApacheCommonsFileUpload)来解析multipart/form-data这种复杂的请求类型。然而,从Servlet3.0规范(已集成到JakartaEE)开始,文件上传功能已被内置到API中,因此不再需要引入commons-fileupload依赖。下面实例演示如何在Servlet中实现文件上传功能。411.1.1创建表单清单11-1所示的代码是一个简单的文件上传页面,通过设置enctype="multipart/form-data"编码类型的表单,提供文件选择控件和上传按钮,用户可以选择本地文件并提交到服务器端的./upload接口进行处理。511.1.1创建表单(清单11-1upload.jsp)<%@pagelanguage="java"contentType="text/html;charset=UTF-8"pageEncoding="UTF-8"%><!DOCTYPEhtml><html><head><title>上传文件</title></head><body><%--文件上传功能标题--%><h2>UploadFile</h2><%--文件上传表单:action="./upload":指定表单提交的服务器端处理地址method="post":必须使用POST方法传输文件enctype="multipart/form-data":必须设置此编码类型才能传输文件--%><formaction="./upload"method="post"enctype="multipart/form-data"><%--文件选择输入框:type="file":定义文件上传控件name="file":与服务器端接收参数名保持一致--%><inputtype="file"name="file"width="200"/><br><br><%--表单提交按钮--%><inputtype="submit"value="上传"/></form></body></html>611.1.1创建表单上述表单是文件上传功能的前端基础。要使其工作,必须满足三个关键点:1)method="post":文件内容通过请求体发送,GET方法无法传输文件。2)enctype="multipart/form-data":这是最重要的属性。它告知浏览器不要使用默认的application/x-www-form-urlencoded编码,而是使用“多部分”格式来封装文件数据。3)<inputtype="file"name="file">:提供文件选择框。name="file"属性是服务器端request.getPart("file")得以获取文件的关键标识。711.1.2创建Servlet编写一个Servlet,用于处理文件上传的请求。如果需要启用Servlet的内置文件上传处理能力,仅需一个关键步骤:在接收文件的Servlet类上,添加jakarta.servlet.annotation.MultipartConfig注解。这个注解会通知Servlet容器(如Tomcat),告知其“这个Servlet准备好接收multipart/form-data请求了”。一旦Servlet被@MultipartConfig标记,容器就会自动处理复杂的数据解析。完成配置后,就可以在Servle中,通过request.getPart()方法轻松获取上传的文件数据。上传功能的Servlet完整的代码如清单11-2所示。811.1.2创建Servlet(清单11-2FileUploadServlet.java)1/3packagecom.example.ch11;importjakarta.servlet.ServletException;importjakarta.servlet.annotation.MultipartConfig;importjakarta.servlet.annotation.WebServlet;importjakarta.servlet.http.HttpServlet;importjakarta.servlet.http.HttpServletRequest;importjakarta.servlet.http.HttpServletResponse;importjakarta.servlet.http.Part;importjava.io.File;importjava.io.IOException;/***文件上传处理Servlet*@WebServlet("/upload")定义Servlet访问路径*@MultipartConfig注解表明该Servlet期望接收"multipart/form-data"类型的请求*@MultipartConfig注解是Servlet3.0+内置文件上传支持所必需的。*/@WebServlet("/upload")@MultipartConfigpublicclassFileUploadServletextendsHttpServlet{privatestaticfinallongserialVersionUID=1L;/***处理POST请求(文件上传表单)911.1.2创建Servlet(清单11-2FileUploadServlet.java)2/3*@paramrequestHTTP请求对象*@paramresponseHTTP响应对象*/protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{//设置响应内容类型和编码response.setContentType("text/html;charset=UTF-8");response.setCharacterEncoding("UTF-8");//定义文件上传的目录//getServletContext().getRealPath("")获取Web应用的根目录//File.separator提供了跨平台的路径分隔符StringuploadPath=getServletContext().getRealPath("")+File.separator+"uploads";//创建上传目录(如果它不存在)FileuploadDir=newFile(uploadPath);if(!uploadDir.exists()){uploadDir.mkdir();}StringfileName="";try{//使用request.getPart("file")获取文件部分//"file"必须与upload.jsp中<inputtype="file"name="file">的name属性匹配PartfilePart=request.getPart("file");1011.1.2创建Servlet(清单11-2FileUploadServlet.java)3/3//获取提交的文件名fileName=filePart.getSubmittedFileName();if(fileName!=null&&!fileName.isEmpty()){//构建完整的文件保存路径StringfilePath=uploadPath+File.separator+fileName;//将文件写入服务器的指定路径filePart.write(filePath);//向客户端返回成功消息response.getWriter().println("上传成功,保存在服务器的位置:"+filePath);}else{response.getWriter().println("没有选择文件。");}}catch(Exceptione){//处理文件上传过程中的异常response.getWriter().println("文件上传失败:"+e.getMessage());}}}1111.1.2创建Servlet上述Servlet是处理文件上传的核心。@MultipartConfig注解是关键,它激活了Servlet3.0+内置的文件上传支持,允许直接使用request.getPart()来获取文件数据。在doPost方法中,首先使用getServletContext().getRealPath("")来获取Web应用在服务器上的真实部署路径,并以此为基础创建uploads目录。随后,通过filePart.getSubmittedFileName()获取用户上传的原始文件名,并最终调用filePart.write(filePath)将文件流写入服务器磁盘,完成保存。【注意】在实际项目中,文件应存储在项目目录之外的独立磁盘路径(如D:\uploads)或云存储服务(如OSS)中,并通过虚拟目录映射进行访问,以防止重新部署导致数据丢失。需要确保对上传的文件进行验证,防止恶意文件上传。可以在@MultipartConfig注解中设置maxFileSize属性限制文件大小。另外,需要确保文件存储路径的合法性和安全性。1211.1.3部署和运行如图11-1所示,将项目部署到Tomcat中,并访问upload.jsp页面。选择文件并单击“上传”提交表单。http://localhost:8080/ch11/upload.jsp图11-1文件上传界面1311.1.3部署和运行等待上传完成后,服务器返回响应,页面显示文件已成功保存的服务器绝对路径,如图11-2所示。图11-2文件上传结果1411.1.4多文件上传在实际应用中,需要一次上传多个文件,并且对文件的大小和类型进行限制。Servlet3.0+的@MultipartConfig注解和request.getParts()方法提供了强大的支持。下面实例演示如何实现多文件上传功能。◆创建多文件上传表单修改upload.jsp文件,在<inputtype="file">标签中添加multiple属性,允许用户选择多个文件。实例代码如清单11-3所示。1511.1.4多文件上传(清单11-3upload_multi.jsp)<%@pagelanguage="java"contentType="text/html;charset=UTF-8"pageEncoding="UTF-8"%><!DOCTYPEhtml><html><head><title>多文件上传</title></head><body><h4>多文件上传</h4><%--1.action指向FileUploadMultiServlet2.method必须为"post"3.enctype必须为"multipart/form-data"--%><formaction="./uploadMulti"method="post"enctype="multipart/form-data"><labelfor="files">选择文件:</label><%--添加multiple属性,允许选择多个文件--%><inputtype="file"name="files"id="files"width="200"multiple/><br><br><inputtype="submit"value="上传"/></form></body></html>1611.1.4多文件上传◆创建Servlet处理多文件上传与校验接下来,创建一个FileUploadMultiServlet类,用于处理多文件上传请求,并增加文件大小和类型的校验。FileUploadMultiServlet.java代码如清单11-4所示。1711.1.4多文件上传(清单11-4FileUploadMultiServlet.java)1/4packagecom.example.ch11;importjakarta.servlet.ServletException;importjakarta.servlet.annotation.MultipartConfig;importjakarta.servlet.annotation.WebServlet;importjakarta.servlet.http.HttpServlet;importjakarta.servlet.http.HttpServletRequest;importjakarta.servlet.http.HttpServletResponse;importjakarta.servlet.http.Part;importjava.io.File;importjava.io.IOException;importjava.io.PrintWriter;importjava.util.Collection;/***处理多文件上传并进行安全校验的Servlet*@WebServlet("/uploadMulti")定义访问路径*@MultipartConfig注解:*-启用Servlet3.0+的文件上传功能*-maxFileSize:设置单个文件的最大限制(这里是10MB)*-maxRequestSize:设置整个请求的最大限制(这里是50MB)*/@WebServlet("/uploadMulti")@MultipartConfig(1811.1.4多文件上传(清单11-4FileUploadMultiServlet.java)2/4maxFileSize=1024*1024*10,//10MBmaxRequestSize=1024*1024*50//50MB)publicclassFileUploadMultiServletextendsHttpServlet{privatestaticfinallongserialVersionUID=2L;protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{response.setContentType("text/html;charset=UTF-8");response.setCharacterEncoding("UTF-8");PrintWriterout=response.getWriter();//1.定义上传目录(与FileUploadServlet相同)StringuploadPath=getServletContext().getRealPath("")+File.separator+"uploads";FileuploadDir=newFile(uploadPath);if(!uploadDir.exists()){uploadDir.mkdir();}try{//2.使用request.getParts()获取所有上传的文件部分Collection<Part>fileParts=request.getParts();if(fileParts.isEmpty()||(fileParts.size()==1&&fileParts.iterator().next().getSize()==0)){out.println("<h3>没有选择任何文件。</h3>");1911.1.4多文件上传(清单11-4FileUploadMultiServlet.java)3/4return;}out.println("<h3>文件上传状态:</h3>");for(PartfilePart:fileParts){StringfileName=filePart.getSubmittedFileName();//确保fileName不为null且不为空if(fileName!=null&&!fileName.isEmpty()){//3.安全校验:检查文件类型(白名单或黑名单)if(fileName.endsWith(".exe")||fileName.endsWith(".jsp")){out.println(String.format("文件'%s'上传失败:不允许的文件类型。<br>",fileName));continue;//跳过此文件,继续处理下一个}//4.保存文件StringfilePath=uploadPath+File.separator+fileName;filePart.write(filePath);out.println(String.format("文件'%s'上传成功。<br>",fileName));}}}catch(IllegalStateExceptione){//5.异常处理:捕获文件大小超限的异常out.println("<h3>文件上传失败:</h3>");if(e.getMessage().contains("maxFileSize")){2011.1.4多文件上传(清单11-4FileUploadMultiServlet.java)4/4out.println("上传失败:单个文件大小超过了10MB的限制。");}elseif(e.getMessage().contains("maxRequestSize")){out.println("上传失败:总上传文件大小超过了50MB的限制。");}else{out.println("上传失败:"+e.getMessage());}}catch(Exceptione){//其他异常out.println("<h3>文件上传时发生意外错误:</h3>");out.println(e.getMessage());}}}2111.1.4多文件上传将项目重新部署到Tomcat中,访问upload_multi.jsp页面。选择多个文件并单击“上传”提交表单,如图11-3所示。图11-3多文件上传界面2211.2文件下载在JavaWeb应用中,使用超链接下载文件和通过Servlet下载文件是两种常见的实现方式。下面分别介绍这两种方法。2311.2.1使用超链接下载文件(清单11-5download.jsp)在JSP页面中实现超链接文件下载需完成四个关键步骤:首先将目标文件置于webapp/uploads等可访问目录;接着在JSP页面创建下载链接;然后确保Tomcat等服务器已开启目录访问权限;最后为非常规扩展名文件配置正确MIME类型。整个过程依托服务器静态资源处理机制,无需复杂编码即可实现高效下载。实例代码如清单11-5所示。<%@pagecontentType="text/html;charset=UTF-8"language="java"%><html><head><title>下载文件</title></head><body><ahref="./uploads/test.docx">下载文件</a></body></html>2411.2.1使用超链接下载文件上述代码中,uploads/test.docx是相对于Web应用根目录的文件路径。2511.2.1使用超链接下载文件将download.jsp页面部署到Tomcat中,访问并单击“下载文件”。单击链接后,浏览器弹出文件下载或预览窗口,显示结果如图11-4所示。http://localhost:8080/ch11/download.jsp图11-4超链接方式实现文件下载【注意】然而,它存在显著的安全风险:1)暴露服务器存储结构:直接展示文件的真实访问地址,攻击者可轻易解析目录结构并发起遍历攻击。2)文件类型与位置限制:通常只能下载Web应用程序根目录或其子目录下的文件。对于浏览器可直接打开的文件类型(如文本、图片、PDF等),超链接会触发直接预览而非下载。因此,在安全性要求较高的Web应用中,不建议采用超链接直连文件的方案。2611.2.2使用Servlet下载文件在Servlet中实现文件下载需系统化完成四个关键环节:首先创建继承HttpServlet的类并通过@WebServlet注解映射下载URL(如/download),在doGet方法中构建完整下载流程;接着使用FileInputStream结合ServletContext.getRealPath()精准定位服务器文件,同时实施路径安全校验防止遍历攻击;然后配置核心响应头——通过setContentType()指定MIME类型、setContentLengthLong()声明文件尺寸、setHeader("Content-Disposition","attachment;filename=...")触发下载行为并解决中文文件名编码问题;最后采用try-with-resources确保资源释放,利用缓冲区通过response.getOutputStream()高效传输文件内容。这种方案融合了权限控制与大文件处理能力,是企业级应用的首选架构。实例代码如清单11-6所示。2711.2.2使用Servlet下载文件(清单11-6FileDownloadServlet.java)1/2packagecom.example.ch11;importjava.io.*;importjakarta.servlet.*;importjakarta.servlet.http.*;@WebServlet("/download")publicclassFileDownloadServletextendsHttpServlet{protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{

//获取请求参数中的文件名(注意:在生产环境中,需要对文件名进行验证和清理)StringfileName=request.getParameter("fileName");

//构建文件的完整路径(这里假设文件存储在WEB-INF/files目录下)StringfilePath=getServletContext().getRealPath("/files")+File.separator+fileName;FiledownloadFile=newFile(filePath);response.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");if(!downloadFile.exists()){response.getWriter().println("下载失败,文件不存在,请创建一个名称为"+fileName+"文件,并放到以下对应路径,以测试下载功能。<br>"+filePath);return;}2811.2.2使用Servlet下载文件(清单11-6FileDownloadServlet.java)2/2FileInputStreaminStream=newFileInputStream(downloadFile);

//获取MIME类型StringmimeType=getServletContext().getMimeType(filePath);if(mimeType==null){mimeType="application/octet-stream";}

//设置响应头

response.setContentType(mimeType);

response.setContentLength((int)downloadFile.length());

StringheaderKey="Content-Dispos

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论