Java开发网站总结——Servlet实现图片上传、验证码实现

来源:互联网 发布:淘宝外宣语言 编辑:程序博客网 时间:2024/06/05 18:47

最近用JSP+Servlet写了一个网站,由于自己很少做过网站方面的开发,在这里记录一下这次开发的总结。一部分内容来源于其他博客内容。如果有错误的地方,还请指出。

1.图片的上传

        在网站开发中,通常会涉及图片上传的功能。图片上传使用到了DiskFileItemFactory、ServletFileUpload、FileItemIterator和FileItemStream这几个类。下面这段Java代码就是实现从前端传递来的表单中读取图片数据功能的。
        首先,获得FileItemIterator的迭代对象items,通过它来迭代表单的每个域。items.next()返回的是fileItemStream对象,fileItemStream.openStream()这个方法可以得到一个InputStream输入流对象。fileItemStream.isFormField()方法可以用来查看当前的表单项是一个文件,还是一个普通的输入项。new String(fileItemStream.getFieldName().getBytes("ISO-8859-1"), "utf-8");这个代码可以获取到表单输入域的name属性,然后再通过Streams.asString(inputStream, "utf-8");就可得到这个表单的value值。
        注意,因为要上传文件的话,表单需要增加enctype="multipart/form-data" 这个属性,这代表表单使用的是MIME编码。默认情况,这个编码格式是application/x-www-form-urlencoded,不能用于文件上传;只有使用了multipart/form-data,才能完整的传递文件数据。enctype="multipart/form-data"是上传二进制数据; form里面的input的值以2进制的方式传过去,因此传统的request.getParameter()方法将不能获取到表单input的内容,需要使用Streams.asString(inputStream, "utf-8"),其中inputStream是FileItemStream对象通过openStream方法得到的。
如果fileItemStream.isFormField()返回false的话,就代表当前要处理的FileItemStream对象是一个文件。文件的保存比较简单,就是将输入流保存到文件,不再赘述。

[html] view plain copy
  1. <form id="myform" name="myform" method="post" enctype="multipart/form-data" action="myServlet">  

[java] view plain copy
  1. package Util;  
  2.   
  3. import DataBaseFile.Volunteer_info;  
  4.   
  5. import org.apache.tomcat.util.http.fileupload.FileItemIterator;  
  6. import org.apache.tomcat.util.http.fileupload.FileItemStream;  
  7. import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;  
  8. import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;  
  9. import org.apache.tomcat.util.http.fileupload.util.Streams;  
  10.   
  11. import javax.servlet.http.HttpServletRequest;  
  12. import javax.servlet.http.HttpServletResponse;  
  13. import javax.servlet.http.HttpSession;  
  14.   
  15. import java.io.*;  
  16. import java.util.Random;  
  17.   
  18. public class saveUserInfo {  
  19.     // 获取行分隔符  
  20.   
  21.     public static void upload(HttpServletRequest request,  
  22.             HttpServletResponse response) throws Exception {  
  23.   
  24.         HttpSession session = request.getSession();  
  25.         String name = null;  
  26.         String id_card = null;  
  27.         String password = null;  
  28.         String email = null;  
  29.         String phone = null;  
  30.         String english_level = null;  
  31.         String image = null;  
  32.         String id_card_image = null;  
  33.   
  34.         DiskFileItemFactory factory = new DiskFileItemFactory();  
  35.         ServletFileUpload sfu = new ServletFileUpload(factory);  
  36.         sfu.setFileSizeMax(1024 * 1024);  
  37.   
  38.         FileItemIterator items = sfu.getItemIterator(request);  
  39.           
  40.         // 判断路径是否存在,不存在则创建目录  
  41.         String contextPathString = request.getSession().getServletContext()  
  42.                 .getRealPath("/");  
  43.         contextPathString += "/CDMetro/images/userImages";  
  44.         File parentfile = new File(contextPathString);  
  45.         if (!parentfile.exists() && !parentfile.isDirectory()) {  
  46.             if (!parentfile.mkdir())  
  47.                 System.out.println("目录创建失败");  
  48.         }  
  49.   
  50.         Random rdRandom = new Random(100000);  
  51.         String randNameString = null;  
  52.         FileItemStream fileItemStream = null;  
  53.         String filename = null;  
  54.         String suffixName = null;  
  55.         String fieldName = null;  
  56.         InputStream inputStream = null;  
  57.         BufferedOutputStream bos = null;  
  58.         BufferedInputStream bis = null;  
  59.         byte[] buffer = new byte[1024];  
  60.         int len = -1;  
  61.   
  62.         while (items.hasNext()) {  
  63.             fileItemStream = items.next();  
  64.             try {  
  65.                 inputStream = fileItemStream.openStream();  
  66.             } catch (Exception e1) {  
  67.                 // TODO Auto-generated catch block  
  68.                 System.out.println("图片太大了!");  
  69.                 return;  
  70.             }  
  71.             if (fileItemStream.isFormField()) {  
  72.                 fieldName = new String(fileItemStream.getFieldName().getBytes(  
  73.                         "ISO-8859-1"), "utf-8");  
  74.                 if (fieldName.equals("username")) {  
  75.                     name = Streams.asString(inputStream, "utf-8");  
  76.   
  77.                 } else if (fieldName.equals("password")) {  
  78.                     password = Streams.asString(inputStream, "utf-8");  
  79.   
  80.                 } else if (fieldName.equals("IDNumber")) {  
  81.                     id_card = Streams.asString(inputStream, "utf-8");  
  82.   
  83.                 } else if (fieldName.equals("Email")) {  
  84.                     email = Streams.asString(inputStream, "utf-8");  
  85.   
  86.                 } else if (fieldName.equals("phone")) {  
  87.                     phone = Streams.asString(inputStream, "utf-8");  
  88.   
  89.                 } else if (fieldName.equals("englishlevel")) {  
  90.                     english_level = Streams.asString(inputStream, "utf-8");  
  91.   
  92.                 } else {  
  93.                       
  94.                 }  
  95.                 continue;  
  96.             }  
  97.           
  98.             fieldName = new String(fileItemStream.getFieldName().getBytes(  
  99.                     "ISO-8859-1"), "utf-8");  
  100.             filename = fileItemStream.getName(); // 获取文件名  
  101.             if (filename != null && !filename.equals(""))  
  102.                 suffixName = filename.substring(filename.lastIndexOf("."));  
  103.             else  
  104.                 continue;  
  105.   
  106.             randNameString = NowTime.getFormatTime("yyyyMMddHHmmss")  
  107.                     + rdRandom.nextInt();  
  108.   
  109.             filename = randNameString + fieldName + suffixName;  
  110.             File mFile = new File(parentfile, filename);  
  111.             bos = new BufferedOutputStream(new FileOutputStream(mFile));  
  112.             bis = new BufferedInputStream(inputStream);  
  113.               
  114.             if (fieldName.equals("image")) {  
  115.                 image = filename;  
  116.             } else if (fieldName.equals("id_card_image")) {  
  117.                 id_card_image = filename;  
  118.             }  
  119.   
  120.             try {  
  121.                 while ((len = bis.read(buffer)) != -1) {  
  122.                     bos.write(buffer, 0, len);  
  123.                 }  
  124.             } catch (Exception e) {  
  125.                 // TODO: handle exception  
  126.                 System.out.println("图片太大了!");  
  127.                 return;  
  128.             } finally {  
  129.                 bos.flush();  
  130.                 bos.close();  
  131.                 bis.close();  
  132.             }  
  133.               
  134.         }  
  135.   
  136.         。。。。。。  
  137.     }  
  138. }  

2.网站验证码的生成。

       这部分代码我是从别人的博客上找的,只做了细小的改动,在这里就简单的贴一下,代码注释也比较详细。就是通过随机数生成一些数字,将它绘制到图片上,然后再随机地在图片上绘制一些线条,以达到干扰图片的效果。
[java] view plain copy
  1. package Util;  
  2.   
  3. import java.awt.Color;  
  4. import java.awt.Font;  
  5. import java.awt.Graphics;  
  6. import java.awt.image.BufferedImage;  
  7. import java.util.Random;  
  8.   
  9. public class AuthCode {  
  10.     public static final int AUTHCODE_LENGTH = 5;        //验证码长度  
  11.     public static final int SINGLECODE_WIDTH = 15;  //单个验证码宽度  
  12.     public static final int SINGLECODE_HEIGHT = 30//单个验证码高度  
  13.     public static final int SINGLECODE_GAP = 4;     //单个验证码之间间隔  
  14.     public static final int IMG_WIDTH = AUTHCODE_LENGTH * (SINGLECODE_WIDTH + SINGLECODE_GAP);  
  15.     public static final int IMG_HEIGHT = SINGLECODE_HEIGHT;  
  16.       
  17.     public static String getAuthCode() {  
  18.         StringBuilder authCode = new StringBuilder("");  
  19.         for(int i = 0; i < AUTHCODE_LENGTH; i++) {  
  20.             authCode.append(new Random().nextInt(10));  
  21.         }  
  22.         return authCode.toString();  
  23.     }  
  24.       
  25.     public static BufferedImage getAuthImg(String authCode) {  
  26.         //设置图片的高、宽、类型  
  27.         //RGB编码:red、green、blue  
  28.         BufferedImage img = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, BufferedImage.TYPE_INT_BGR);  
  29.         //得到图片上的一个画笔  
  30.         Graphics g = img.getGraphics();  
  31.         //设置画笔的颜色,用来做背景色  
  32.         g.setColor(Color.YELLOW);  
  33.         //用画笔来填充一个矩形,矩形的左上角坐标,宽,高  
  34.         g.fillRect(00, IMG_WIDTH, IMG_HEIGHT);  
  35.         //将画笔颜色设置为黑色,用来写字  
  36.         g.setColor(Color.BLACK);  
  37.         //设置字体:宋体、不带格式的、字号  
  38.         g.setFont(new Font("宋体", Font.PLAIN, SINGLECODE_HEIGHT + 5));  
  39.           
  40.         //输出数字  
  41.         char c;  
  42.         for(int i = 0; i < authCode.toCharArray().length; i++) {  
  43.             //取到对应位置的字符  
  44.             c = authCode.charAt(i);  
  45.             //画出一个字符串:要画的内容,开始的位置,高度  
  46.             g.drawString(c + "", i * (SINGLECODE_WIDTH + SINGLECODE_GAP)+ SINGLECODE_GAP / 2, IMG_HEIGHT);  
  47.         }  
  48.         Random random = new Random();  
  49.         //干扰素  
  50.         for(int i = 0; i < 20; i++) {  
  51.             int x = random.nextInt(IMG_WIDTH);  
  52.             int y = random.nextInt(IMG_HEIGHT);  
  53.             int x2 = random.nextInt(IMG_WIDTH);  
  54.             int y2 = random.nextInt(IMG_HEIGHT);  
  55.             g.drawLine(x, y, x + x2, y + y2);  
  56.         }  
  57.         return img;  
  58.     }  
  59. }  
         ImageIO可以将BufferedImage对象直接写到response的输出流中,Servlet中对验证码请求的处理这样的:
[java] view plain copy
  1. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  2.         // TODO Auto-generated method stub  
  3.         String codeString = AuthCode.getAuthCode();  
  4.         request.getSession().setAttribute("authCode", codeString);  
  5.         try {  
  6.             ImageIO.write(AuthCode.getAuthImg(codeString), "JPEG", response.getOutputStream());  
  7.         } catch (Exception e) {  
  8.             // TODO Auto-generated catch block  
  9.             e.printStackTrace();  
  10.             System.out.println("图片验证码发送错误");  
  11.         }  
  12.     }  
         Servlet中通过这样的方法来判断用户输入的验证码是否正确:
[java] view plain copy
  1. protected void doGet(HttpServletRequest request,  
  2.             HttpServletResponse response) throws ServletException, IOException {  
  3.         // TODO Auto-generated method stub  
  4.         String code = request.getParameter("myCode");  
  5.         if (code == null || code ==""){  
  6.             response.getWriter().print("codeFalse");  
  7.             return;  
  8.         }  
  9.         String rightCodeString = (String) request.getSession().getAttribute(  
  10.                 "authCode");  
  11.         if (code.equals(rightCodeString)) {  
  12.             response.getWriter().print("codeTrue");  
  13.         } else {  
  14.             response.getWriter().print("codeFalse");  
  15.         }  
  16.     }  
        在前端页面中,可这样书写验证码的请求,只要在img的src中写出servlet路径就可以了:
[html] view plain copy
  1. <input id="authcode" name="authcode" type="text" style="height: 30px; width: 80px;" onchange="checkAuthCode()" /><a href="javascript:void(0);" onclick="getNewAuthCode();"><img id="authcodeImage" name="authcodeImage" src="getAuthCodeServlet" style="margin-left: 10px; height: 30px; width: 100px;" /></a>  
        当用户点击验证码图片时调用js函数getNewAuthCode,可更换验证码图片。注意:添加Math.random();的原因是,如果不添加的话那么由于图片的请求地址不变,浏览器是不会去更新图片的。
[javascript] view plain copy
  1. function getNewAuthCode() {  
  2.         document.getElementById("authcodeImage").src = "getAuthCodeServlet?"  
  3.                 + Math.random();  
  4.     }  
         用户输入完验证码后,可通过onchange事件,利用Ajax,判断用户输入的验证码是否正确。
[javascript] view plain copy
  1. function checkAuthCode() {  
  2.         var xmlhttp;  
  3.         if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari  
  4.             xmlhttp = new XMLHttpRequest();  
  5.         } else {// code for IE6, IE5  
  6.             xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");  
  7.         }  
  8.         xmlhttp.onreadystatechange = function() {  
  9.             if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {  
  10.                 var responseText = xmlhttp.responseText;  
  11.                 if (responseText == "codeFalse") {  
  12.                     alert("验证码输入错误请重新输入");  
  13.                     getNewAuthCode();  
  14.                     //window.location.reload();  
  15.                     return false;  
  16.                 } else if (responseText == "codeTrue") {  
  17.                     document.getElementById("torf").value = "valid";  
  18.                     return true;  
  19.                 } else {  
  20.                     return false;  
  21.                 }  
  22.             }  
  23.         }  
  24.         var num = document.getElementById("authcode").value;  
  25.         xmlhttp.open("GET""checkCode?myCode=" + num, "true");  
  26.         xmlhttp.setRequestHeader("Content-type",  
  27.                 "application/x-www-form-urlencoded");  
  28.         xmlhttp.send();  
  29.     }  
0 0