一、文件上传
在TCP/IP中,最早出现的文件上传机制是FTP。它是将文件由客户端发送到服务器的标准机制。
但是在jsp编程中不能使用FTP方法来上传文件,这是由jsp运行机制所决定的。
通过为表单元素设置method="post" enctype="multipart/form-data"属性,让表单提交的数据以二进制编码的方式提交,在接收此请求的Servlet中用二进制流来获取内容,就可以取得上传文件的内容,从而是实现文件的上传。
enctype属性有三种类型
实例【jsp+servlet】
1、上传实现思路
(一)、环境搭建【配置web.xml创建UploadServlet】
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <display-name></display-name> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>UploadServlet</servlet-name> <servlet-class>com.wuhn.scxz.servlet.UploadServlet</servlet-class> </servlet> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>DownloadServlet</servlet-name> <servlet-class>com.wuhn.scxz.servlet.DownloadServlet</servlet-class> </servlet> <!-- 上传servlet --> <servlet-mapping> <servlet-name>UploadServlet</servlet-name> <url-pattern>/UploadServlet.do</url-pattern> </servlet-mapping> <!-- 下载servlet --> <servlet-mapping> <servlet-name>DownloadServlet</servlet-name> <url-pattern>/DownloadServlet.do</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
(二)、前台页面配置【Form的method设置为post,enctype配置为multipart/form-data】
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML> <html> <head> <base href="<%=basePath%>"> <title>上传</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <link rel="stylesheet" type="text/css" href="<%=path%>/css/common.css"> <script type="text/javascript" src="<%=path%>/js/jquery-1.11.1.js"></script> <script type="text/javascript"> /*//js 预览功能因为回去不到本地实际的路径,所以无法实现。因为浏览器考虑到安全性的问题,限制了获取真实的本机路径,只能这样C:\fakepath\img1-lg.jpg function showPreview(obj){ var imgPath = obj.value; console.log(imgPath); document.getElementById("previewImg").innerHTML="<img src='"+imgPath+"'/>"; } */ </script> </head> <body> <form action="<%=path%>/UploadServlet.do" method="post" enctype="multipart/form-data"> 请选择图片:<input id="myfile" name="myfile" type="file"/> <input type="submit" value="提交" />${result} </form> </body> </html>
(三)、后台Servlet实现【保存上传文件】
实现的步骤:
1、获取request当中的流信息,保存到临时文件。
2、从临时文件中得到上传的文件名及文件内容起止位置。
3、根据文件起止位置,读取上传文件内容,保存到本地。
package com.wuhn.scxz.servlet; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.RandomAccessFile; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author wuhn * @创建时间 2015-12-07 * @功能 上传文件 * **/ public class UploadServlet extends HttpServlet { /** * get方法 * **/ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response);//默认为post提交 } /** * post方法 * **/ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("测试:已接收到请求"); //从request当中获取流信息 InputStream inputStream = request.getInputStream(); //tempFile指向临时文件 String tempFileName= "D:\\tempFile"; File tempFile = new File(tempFileName); //fileOutputStream文件输出流指向这个临时文件 FileOutputStream fileOutputStream = new FileOutputStream(tempFile); byte b[] = new byte[1024]; int n; while ((n = inputStream.read(b)) != -1) { fileOutputStream.write(b, 0, n); } //关闭输出流、输入流 fileOutputStream.close(); inputStream.close(); //关闭上传文件的名称 RandomAccessFile randomFile = new RandomAccessFile(tempFile,"r"); randomFile.readLine(); String str = randomFile.readLine(); String strSplit = str.split(";")[str.split(";").length-1]; int beginIndex = strSplit.indexOf("\"")+1; int endIndex = strSplit.lastIndexOf("\""); System.out.println(strSplit+" beginIndex:"+beginIndex+" endIndex:"+endIndex); String filename = strSplit.substring(beginIndex, endIndex); System.out.println("filename:"+filename); //重新定位文件指针到文件头 randomFile.seek(0); long startPosition = 0; int i =1; //获取文件内容的开始位置 while ((n = randomFile.readByte())!=-1 && i<4) { if(n == '\n'){ startPosition = randomFile.getFilePointer(); i++; } } startPosition = startPosition-1; //获取文件内容的结束位置 randomFile.seek(randomFile.length()); long endPosition = randomFile.getFilePointer(); int j = 1; while (endPosition >=0 && j<2) { endPosition--; randomFile.seek(endPosition); if(randomFile.readByte()=='\n'){ j++; } } endPosition = endPosition - 1; //设置保存上传文件的路径 String realPath = getServletContext().getRealPath("/")+"images/upload";//这是服务器上的地址 //System.out.println("保存上传文件的路径:"+realPath); File fileUploadFile = new File(realPath); if (!fileUploadFile.exists()) { fileUploadFile.mkdir(); } File saveFile = new File(realPath, filename); RandomAccessFile randomAccessFile = new RandomAccessFile(saveFile, "rw"); //从临时文件当中读取文件内容(根据起止位置获取) randomFile.seek(startPosition); while (startPosition<endPosition) { randomAccessFile.write(randomFile.readByte()); startPosition = randomFile.getFilePointer(); } //关闭输入输出流、删除临时文件 randomAccessFile.close(); randomFile.close(); //返回 request.setAttribute("result", "上传成功!"); RequestDispatcher dispatcher = request.getRequestDispatcher("jsp/01.jsp"); dispatcher.forward(request, response); } }
二、文件下载
1、需要通过HttpServletResponse.setContentType方法设置Content-Type头字段的值,为浏览器无法使用某种方式或激活某哥程序来处理的MIME类型,例如,“application/octet-stream”或“application/x-msdownload”等。
2、需要通过HttpServletResponse.setHeader方法设置Content-Disposition头的值为“attachment;filename=文件名”。
3、读取下载文件,调用HttpServletResponse.getOutputStream方法返回的ServletOutputStream对象来向客户端写入附件文件内容。
实现【jsp+servlet】
(一)、配置web.xml【配置wen.xml,创建DownloadServlet】
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <display-name></display-name> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>UploadServlet</servlet-name> <servlet-class>com.wuhn.scxz.servlet.UploadServlet</servlet-class> </servlet> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>DownloadServlet</servlet-name> <servlet-class>com.wuhn.scxz.servlet.DownloadServlet</servlet-class> </servlet> <!-- 上传servlet --> <servlet-mapping> <servlet-name>UploadServlet</servlet-name> <url-pattern>/UploadServlet.do</url-pattern> </servlet-mapping> <!-- 下载servlet --> <servlet-mapping> <servlet-name>DownloadServlet</servlet-name> <url-pattern>/DownloadServlet.do</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
(二)、前台页面开发【通过超链接的方式发起文件下载请求】
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML> <html> <head> <base href="<%=basePath%>"> <title>下载</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <link rel="stylesheet" type="text/css" href="<%=path%>/css/common.css"> <script type="text/javascript" src="<%=path%>/js/jquery-1.11.1.js"></script> </head> <body> 下载:<a href="<%=path%>/DownloadServlet.do?filename=test.txt">test.txt</a> ${errorResult} </body> </html>
(三)、后台Servlet【设置响应类型及响应头输出流写入文件内容】
package com.wuhn.scxz.servlet; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author wuhn * @创建时间 2015-12-07 * @功能 下载文件 * **/ public class DownloadServlet extends HttpServlet { /** *get方法 * **/ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取文件下载路径 String path = getServletContext().getRealPath("/")+"images/upload"; String filename = request.getParameter("filename"); File file = new File(path + filename); if(file.exists()){ //设置相应类型 response.setContentType("application/x-msdownload");//或者application/octet-stream //设置头信息 response.setHeader("Content-Disposition", "attachment;filename=\""+filename+"\""); InputStream inputStream = new FileInputStream(file); ServletOutputStream outputStream = response.getOutputStream(); byte b[] = new byte[1024]; int n; while ((n=inputStream.read(b)) != -1) { outputStream.write(b, 0, n); } //关闭流、释放资源 outputStream.close(); inputStream.close(); }else{ request.setAttribute("errorResult", "文件不存在,下载失败!"); RequestDispatcher dispatcher = request.getRequestDispatcher("jsp/01.jsp"); dispatcher.forward(request, response); } } /** * post方法 * **/ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response);//默认为get } }
三、项目代码【点击这里下载】