servlet文件上传与下载
2015-08-03 21:02
477 查看
文件上传:
RFC1867协议的请求与响应的特点:
通过浏览器上传文件给服务器,与正常的访问不同,用户通过浏览器给服务器发送的比较复杂,而向浏览器返回的信息
可能是简单的信息,为了规范通过浏览器上传文件到服务器的行为,就设计了一个RFC1867协议,约定上传文件所需要尊守
的规则。
文件上传的本质:
从客户端复制文件到服务端指定目录下面的过程
文件上传表单三要素:
1,使用post方式提交表单
2,为上传表单的每个表单项添加name属性,便于服务器收集
3,在form标签中,加上enctype="multipart/form-data" 只有在上传文件时使用
为了便于上传,需在项目中引入:commons-fileupload-1.2.1.jar和commons-io-1.4.jar两个包
下面演示FileUpload包API的使用:
upload.jsp
FileUploadServlet
WebUtil中部分代码:
上面例子中,在WEB-INF中创建了一个upload文件夹,同时在为了解决不同用户上传相同文件名的问题,使用UUID分别
为每个文件区分,同时为了在upload中的文件夹打散在子文件夹,利用了添加UUID后的UUID文件名的哈希码,得到一个子目
录路径,这样做的好处是:在下载的时候可以通过UUID文件名调用相同的方法获取子目录路径,从而获取输入流。
ListFileServlet
list.jsp
FileDownloadServlet
JAVA中的注解
注解是JDK5,新增的语法功能,就是用@来标识该类,方法,属性的相关信息
注解的作用:通知编译器如何处理被注解修饰过的内容,在某种情况下,可以替代原来的XML或properties等文本文件,
例如hibernate,spring,android 中会证明。
1,@Override
复写父类方法
2,@Deprecated
废弃方法,已经过时。
3,@SuppressWarnings (value="unchecked")
表示通知编译器不要警告
JDK5中的内置注解,不能瞒住企业方方面面的业务续修,所以的按规则,开发注解
自定义注解的生命周期
SOURCE:有且只有在源码级别可见,(不推荐使用)
CLASS: 有且只有在源码和字节码级别可见,(默认),但在运行时,不可见
RUNTIME:在整个类的运行期周,都可见。(即源码,字节码,运行时)
元注解的作用
修饰其它注解的注解,注意:元注解也可以被其它注解修饰
@Retention(RetentionPolicy.RUNTIME):表示该注解可以在运行时,可见
@Target(ElementType.METHOD):表示该注解可以用在哪些地方,默认情况下,该注解可以出现在任何地方
自定义注解应用示例:
DB.java
RFC1867协议的请求与响应的特点:
通过浏览器上传文件给服务器,与正常的访问不同,用户通过浏览器给服务器发送的比较复杂,而向浏览器返回的信息
可能是简单的信息,为了规范通过浏览器上传文件到服务器的行为,就设计了一个RFC1867协议,约定上传文件所需要尊守
的规则。
文件上传的本质:
从客户端复制文件到服务端指定目录下面的过程
文件上传表单三要素:
1,使用post方式提交表单
2,为上传表单的每个表单项添加name属性,便于服务器收集
3,在form标签中,加上enctype="multipart/form-data" 只有在上传文件时使用
为了便于上传,需在项目中引入:commons-fileupload-1.2.1.jar和commons-io-1.4.jar两个包
下面演示FileUpload包API的使用:
upload.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP upload page</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"> <style type="text/css"> .container{ width:400px; margin:100px auto; } ul li{ width:350px; height:50px; list-style:none; } ul li span{ color:red; font-size:30px; } </style> </head> <body> <div class="container"> <form action="${pageContext.request.contextPath}/FileUploadServlet" method="POST" enctype="multipart/form-data"> <ul> <li><span>上传文件</span></li> <li><input id="addLineID" type="button" value="添加上传文件"/></li> <li><input id="uploadID" type="submit" value="上传"/></li> </ul> </form> </div> <script type="text/javascript"> var count = 0 ; document.getElementById("addLineID").onclick = function(){ if(count<5){ var li = document.createElement("li"); //创建input节点 var input = document.createElement("input"); input.type = "file"; input.name = "image"; var button = document.createElement("input"); button.value = "删除"; button.type = "button"; button.onclick = function(){ i--; li.parentNode.removeChild(li); } li.appendChild(input); li.appendChild(button); var ul = document.getElementsByTagName("ul")[0]; ul.insertBefore(li,this.parentNode); count++; }else{ alert("大哥,不能再添加了!"); } } </script> </body> </html>
FileUploadServlet
import itcast.util.WebUtil; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; public class FileUploadServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try{ //设置上传参数编码为UTF-8 request.setCharacterEncoding("UTF-8"); //创建文件上传工厂 DiskFileItemFactory factory = new DiskFileItemFactory(); //设置临时缓存区为100k factory.setSizeThreshold(100*1024); //设置超过100k时,缓存文件的存放路径 factory.setRepository(new File(this.getServletContext().getRealPath("/WEB-INF/temp"))); //创建文件上传对象 ServletFileUpload fileUpload = new ServletFileUpload(factory); //判断是否以RFC协议方式上传文件 if(fileUpload.isMultipartContent(request)){ //解析request中的所有表单字段 List<FileItem> fileItemList = fileUpload.parseRequest(request); for(FileItem fileItem : fileItemList){ //如果是普通字段 if(fileItem.isFormField()){ /* * 做获取字段操作 * String name = fileItem.getFieldName(); * String value = fileItem.getString("UTF-8"); */ }else if(!fileItem.isFormField()){ long size = fileItem.getSize(); if(size > 200*1024){ request.setAttribute("message","<font style='font-size:111px;color:red'>上传文件大 小必须小于或等于200k</font><a href='"+request.getContextPath()+"/upload.jsp'> 继续上传</a><a href='"+request.getContextPath()+"/ListFileServlet'>浏览列表</a>"); request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request,response); continue ; } String contentType = fileItem.getContentType(); String agent = request.getHeader("USER-AGENT"); //获取agent参数,IE有MSIE参数,FF没有该参数 System.out.println(contentType); if(!"image/pjpeg".equals(contentType) && !"image/jpeg".equals(contentType) && !"application/octet-stream".equals(contentType)){ request.setAttribute("message","<font style='font-size:111px;color:red'>上传文件类型 必须是jpg</font><a href='"+request.getContextPath()+"/upload.jsp'>继续上传</a> <a href='"+request.getContextPath()+"/ListFileServlet'>浏览列表</a>"); request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request,response); continue ; } String filename = fileItem.getName(); filename = WebUtil.makeUuidFileName(filename); //创建目录把文件分散在2级子目录下 String uploadPath = WebUtil.makeSubUploadPath(this.getServletContext().getRealPath("/WEB-INF/upload"), filename); //把文件写到服务器自定服务器下面 InputStream is = fileItem.getInputStream(); OutputStream os = new FileOutputStream(new File(uploadPath+"/"+filename)); WebUtil.writeToFile(is, os); fileItem.delete();//删除缓存的临时文件 } } } }catch(Exception e){ } request.setAttribute("message","<font style='font-size:111px;color:green'>上传文件成功</font> <a href='"+request.getContextPath()+"/upload.jsp'>继续上传</a><a href='"+request.getContextPath()+"/ListFileServlet'>浏览列表</a>"); request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request,response); } }
WebUtil中部分代码:
public static String makeUuidFileName(String filename){ return UUID.randomUUID().toString()+"_"+filename; } /* * 该方法是把上传的文件打散在不同的子目录里面 */ public static String makeSubUploadPath(String path,String name){ int code = name.hashCode(); int dir1 = Math.abs(code % 16); //第一级目录 int dir2 = Math.abs((code >> 1) % 16); //第二级目录 File file = new File(path+"/"+dir1+"/"+dir2); if(!file.exists()){ //如果目录不存在就创建该目录 file.mkdirs(); } return file.getPath(); } /** * 把输入流写到输出流里面 * @param is * @param os */ public static void writeToFile(InputStream is,OutputStream os){ try{ int len = 0; byte[] buf = new byte[2048]; while((len = is.read(buf)) > 0){ os.write(buf, 0, len); } }catch(Exception e){ e.printStackTrace(); }finally{ try { if(is != null){ is.close(); } if(os != null){ os.close(); } } catch (IOException e) { e.printStackTrace(); } } } public static String getFileName(String filename){ return filename.substring(filename.indexOf("_")+1); } }
上面例子中,在WEB-INF中创建了一个upload文件夹,同时在为了解决不同用户上传相同文件名的问题,使用UUID分别
为每个文件区分,同时为了在upload中的文件夹打散在子文件夹,利用了添加UUID后的UUID文件名的哈希码,得到一个子目
录路径,这样做的好处是:在下载的时候可以通过UUID文件名调用相同的方法获取子目录路径,从而获取输入流。
ListFileServlet
import itcast.util.WebUtil; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.LinkedHashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ListFileServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取上传文件存放路径 String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload"); //定义一个集合将文件名存放好 Map<String,String> map = new LinkedHashMap<String, String>(); //递归遍历所有文件 getAllFile(uploadPath,map); //将map保存到request中 request.setAttribute("MAP", map); //转发到list.jsp 页面 request.getRequestDispatcher("/WEB-INF/list.jsp").forward(request, response); } public void getAllFile(String uploadPath, Map<String, String> map) { File file = new File(uploadPath); if(file.isFile()){ String uuidFileName = file.getName(); //从uuidName 中截取出filename String filename = WebUtil.getFileName(uuidFileName); map.put(uuidFileName, filename); }else if(file.isDirectory()){ //如果是目录的话 File[] files = file.listFiles(); for(File f : files){ getAllFile(f.getPath(), map); } } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
list.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'list.jsp' starting page</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"> <style type="text/css"> .container{ width:500px; margin:0px auto; } .container ul li{ margin:0px auto; width:400px; list-style:none; height:50px; } .container ul li span{ width:200px; height:50px; text-align: center; display:inline-block; line-height:50px; } </style> </head> <body> <div class="container"> <ul> <li><span>文件名</span><span>下载</span></li> <c:forEach var="item" items="${requestScope.MAP}"> <c:url var="url" value="/FileDownloadServlet"> <c:param name="name" value="${item.key}"></c:param> </c:url> <li><span>${item.value}</span><span><a href="${url}">下载</a></span></li> </c:forEach> </ul> </div> </body> </html>
FileDownloadServlet
import itcast.util.WebUtil; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class FileDownloadServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //解决中文乱码问题 //获取参数中的文件名称 String uuidFileName = request.getParameter("name"); uuidFileName = new String(uuidFileName.getBytes("ISO8859-1"),"UTF-8"); //从uuid文件名中获取文件名 String filename = WebUtil.getFileName(uuidFileName); System.out.println(filename); //因为是中文,要进行URL编码,该方法在Firefox Netscape 5.0 (Windows) 失效 filename = URLEncoder.encode(filename,"UTF-8"); System.out.println(filename); //获取上传文件的根目录 String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload"); //内部是通过uuidFileName的hasCode编码的,所以相同的文件名,可以获取相同的子路径 String path = WebUtil.makeSubUploadPath(uploadPath, uuidFileName); //通知浏览器以下载的方式打开 response.setHeader("content-disposition","attachment;filename="+filename); //从实际文件中读取流 InputStream is = new FileInputStream(path+"/"+uuidFileName); OutputStream os = response.getOutputStream(); //把内容写到浏览器 WebUtil.writeToFile(is, os); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
JAVA中的注解
注解是JDK5,新增的语法功能,就是用@来标识该类,方法,属性的相关信息
注解的作用:通知编译器如何处理被注解修饰过的内容,在某种情况下,可以替代原来的XML或properties等文本文件,
例如hibernate,spring,android 中会证明。
1,@Override
复写父类方法
2,@Deprecated
废弃方法,已经过时。
3,@SuppressWarnings (value="unchecked")
表示通知编译器不要警告
JDK5中的内置注解,不能瞒住企业方方面面的业务续修,所以的按规则,开发注解
自定义注解的生命周期
SOURCE:有且只有在源码级别可见,(不推荐使用)
CLASS: 有且只有在源码和字节码级别可见,(默认),但在运行时,不可见
RUNTIME:在整个类的运行期周,都可见。(即源码,字节码,运行时)
元注解的作用
修饰其它注解的注解,注意:元注解也可以被其它注解修饰
@Retention(RetentionPolicy.RUNTIME):表示该注解可以在运行时,可见
@Target(ElementType.METHOD):表示该注解可以用在哪些地方,默认情况下,该注解可以出现在任何地方
自定义注解应用示例:
DB.java
@Target({METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface DB { String driver() default "com.mysql.jdbc.Driver"; String url() default "jdbc:mysql://127.0.0.1:3306/jdbc"; String user() default "root"; String password() default "root"; } Demo03.java public class Demo03 { @DB public Connection getConnection() throws Exception { Class clazz = this.getClass(); Method getConnectionMethod = clazz.getMethod("getConnection",null); DB dbAnnotation = getConnectionMethod.getAnnotation(DB.class); String driver = dbAnnotation.driver(); String url = dbAnnotation.url(); String user = dbAnnotation.user(); String password = dbAnnotation.password(); Class.forName(driver); return DriverManager.getConnection(url,user,password); } public static void main(String[] args) throws Exception { Demo03 test = new Demo03(); Connection conn = test.getConnection(); System.out.println(conn!=null?"连接成功":"连接失败"); conn.close(); } }
相关文章推荐
- 百钱买百鸡
- MSFlexGrid控件的相关介绍
- C# openfiledialog的使用
- vs 默认的INC和LIB
- hdoj 3635 Dragon Balls【并查集求节点转移次数+节点数+某点根节点】
- SAX 的test
- SAX解析器
- uva 1600
- 欢迎使用CSDN-markdown编辑器
- Linux内核——伙伴系统和slab缓存
- socket选项总结(setsocketopt)
- DOM解析器
- 线性探测法构造哈希表(hash)
- 线性探测法构造哈希表(hash)
- 线性探测法构造哈希表(hash)
- 线性探测法构造哈希表(hash)
- 线性探测法构造哈希表(hash)
- 线性探测法构造哈希表(hash)
- 线性探测法构造哈希表(hash)
- Linux stat 命令