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对象是一个文件。文件的保存比较简单,就是将输入流保存到文件,不再赘述。
- <form id="myform" name="myform" method="post" enctype="multipart/form-data" action="myServlet">
- package Util;
-
- import DataBaseFile.Volunteer_info;
-
- import org.apache.tomcat.util.http.fileupload.FileItemIterator;
- import org.apache.tomcat.util.http.fileupload.FileItemStream;
- import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
- import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
- import org.apache.tomcat.util.http.fileupload.util.Streams;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpSession;
-
- import java.io.*;
- import java.util.Random;
-
- public class saveUserInfo {
-
-
- public static void upload(HttpServletRequest request,
- HttpServletResponse response) throws Exception {
-
- HttpSession session = request.getSession();
- String name = null;
- String id_card = null;
- String password = null;
- String email = null;
- String phone = null;
- String english_level = null;
- String image = null;
- String id_card_image = null;
-
- DiskFileItemFactory factory = new DiskFileItemFactory();
- ServletFileUpload sfu = new ServletFileUpload(factory);
- sfu.setFileSizeMax(1024 * 1024);
-
- FileItemIterator items = sfu.getItemIterator(request);
-
-
- String contextPathString = request.getSession().getServletContext()
- .getRealPath("/");
- contextPathString += "/CDMetro/images/userImages";
- File parentfile = new File(contextPathString);
- if (!parentfile.exists() && !parentfile.isDirectory()) {
- if (!parentfile.mkdir())
- System.out.println("目录创建失败");
- }
-
- Random rdRandom = new Random(100000);
- String randNameString = null;
- FileItemStream fileItemStream = null;
- String filename = null;
- String suffixName = null;
- String fieldName = null;
- InputStream inputStream = null;
- BufferedOutputStream bos = null;
- BufferedInputStream bis = null;
- byte[] buffer = new byte[1024];
- int len = -1;
-
- while (items.hasNext()) {
- fileItemStream = items.next();
- try {
- inputStream = fileItemStream.openStream();
- } catch (Exception e1) {
-
- System.out.println("图片太大了!");
- return;
- }
- if (fileItemStream.isFormField()) {
- fieldName = new String(fileItemStream.getFieldName().getBytes(
- "ISO-8859-1"), "utf-8");
- if (fieldName.equals("username")) {
- name = Streams.asString(inputStream, "utf-8");
-
- } else if (fieldName.equals("password")) {
- password = Streams.asString(inputStream, "utf-8");
-
- } else if (fieldName.equals("IDNumber")) {
- id_card = Streams.asString(inputStream, "utf-8");
-
- } else if (fieldName.equals("Email")) {
- email = Streams.asString(inputStream, "utf-8");
-
- } else if (fieldName.equals("phone")) {
- phone = Streams.asString(inputStream, "utf-8");
-
- } else if (fieldName.equals("englishlevel")) {
- english_level = Streams.asString(inputStream, "utf-8");
-
- } else {
-
- }
- continue;
- }
-
- fieldName = new String(fileItemStream.getFieldName().getBytes(
- "ISO-8859-1"), "utf-8");
- filename = fileItemStream.getName();
- if (filename != null && !filename.equals(""))
- suffixName = filename.substring(filename.lastIndexOf("."));
- else
- continue;
-
- randNameString = NowTime.getFormatTime("yyyyMMddHHmmss")
- + rdRandom.nextInt();
-
- filename = randNameString + fieldName + suffixName;
- File mFile = new File(parentfile, filename);
- bos = new BufferedOutputStream(new FileOutputStream(mFile));
- bis = new BufferedInputStream(inputStream);
-
- if (fieldName.equals("image")) {
- image = filename;
- } else if (fieldName.equals("id_card_image")) {
- id_card_image = filename;
- }
-
- try {
- while ((len = bis.read(buffer)) != -1) {
- bos.write(buffer, 0, len);
- }
- } catch (Exception e) {
-
- System.out.println("图片太大了!");
- return;
- } finally {
- bos.flush();
- bos.close();
- bis.close();
- }
-
- }
-
- 。。。。。。
- }
- }
2.网站验证码的生成。
这部分代码我是从别人的博客上找的,只做了细小的改动,在这里就简单的贴一下,代码注释也比较详细。就是通过随机数生成一些数字,将它绘制到图片上,然后再随机地在图片上绘制一些线条,以达到干扰图片的效果。
- package Util;
-
- import java.awt.Color;
- import java.awt.Font;
- import java.awt.Graphics;
- import java.awt.image.BufferedImage;
- import java.util.Random;
-
- public class AuthCode {
- public static final int AUTHCODE_LENGTH = 5;
- public static final int SINGLECODE_WIDTH = 15;
- public static final int SINGLECODE_HEIGHT = 30;
- public static final int SINGLECODE_GAP = 4;
- public static final int IMG_WIDTH = AUTHCODE_LENGTH * (SINGLECODE_WIDTH + SINGLECODE_GAP);
- public static final int IMG_HEIGHT = SINGLECODE_HEIGHT;
-
- public static String getAuthCode() {
- StringBuilder authCode = new StringBuilder("");
- for(int i = 0; i < AUTHCODE_LENGTH; i++) {
- authCode.append(new Random().nextInt(10));
- }
- return authCode.toString();
- }
-
- public static BufferedImage getAuthImg(String authCode) {
-
-
- BufferedImage img = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, BufferedImage.TYPE_INT_BGR);
-
- Graphics g = img.getGraphics();
-
- g.setColor(Color.YELLOW);
-
- g.fillRect(0, 0, IMG_WIDTH, IMG_HEIGHT);
-
- g.setColor(Color.BLACK);
-
- g.setFont(new Font("宋体", Font.PLAIN, SINGLECODE_HEIGHT + 5));
-
-
- char c;
- for(int i = 0; i < authCode.toCharArray().length; i++) {
-
- c = authCode.charAt(i);
-
- g.drawString(c + "", i * (SINGLECODE_WIDTH + SINGLECODE_GAP)+ SINGLECODE_GAP / 2, IMG_HEIGHT);
- }
- Random random = new Random();
-
- for(int i = 0; i < 20; i++) {
- int x = random.nextInt(IMG_WIDTH);
- int y = random.nextInt(IMG_HEIGHT);
- int x2 = random.nextInt(IMG_WIDTH);
- int y2 = random.nextInt(IMG_HEIGHT);
- g.drawLine(x, y, x + x2, y + y2);
- }
- return img;
- }
- }
ImageIO可以将BufferedImage对象直接写到response的输出流中,Servlet中对验证码请求的处理这样的:
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
-
- String codeString = AuthCode.getAuthCode();
- request.getSession().setAttribute("authCode", codeString);
- try {
- ImageIO.write(AuthCode.getAuthImg(codeString), "JPEG", response.getOutputStream());
- } catch (Exception e) {
-
- e.printStackTrace();
- System.out.println("图片验证码发送错误");
- }
- }
Servlet中通过这样的方法来判断用户输入的验证码是否正确:
- protected void doGet(HttpServletRequest request,
- HttpServletResponse response) throws ServletException, IOException {
-
- String code = request.getParameter("myCode");
- if (code == null || code ==""){
- response.getWriter().print("codeFalse");
- return;
- }
- String rightCodeString = (String) request.getSession().getAttribute(
- "authCode");
- if (code.equals(rightCodeString)) {
- response.getWriter().print("codeTrue");
- } else {
- response.getWriter().print("codeFalse");
- }
- }
在前端页面中,可这样书写验证码的请求,只要在img的src中写出servlet路径就可以了:
- <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();的原因是,如果不添加的话那么由于图片的请求地址不变,浏览器是不会去更新图片的。
- function getNewAuthCode() {
- document.getElementById("authcodeImage").src = "getAuthCodeServlet?"
- + Math.random();
- }
用户输入完验证码后,可通过onchange事件,利用Ajax,判断用户输入的验证码是否正确。
- function checkAuthCode() {
- var xmlhttp;
- if (window.XMLHttpRequest) {
- xmlhttp = new XMLHttpRequest();
- } else {
- xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
- }
- xmlhttp.onreadystatechange = function() {
- if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
- var responseText = xmlhttp.responseText;
- if (responseText == "codeFalse") {
- alert("验证码输入错误请重新输入");
- getNewAuthCode();
-
- return false;
- } else if (responseText == "codeTrue") {
- document.getElementById("torf").value = "valid";
- return true;
- } else {
- return false;
- }
- }
- }
- var num = document.getElementById("authcode").value;
- xmlhttp.open("GET", "checkCode?myCode=" + num, "true");
- xmlhttp.setRequestHeader("Content-type",
- "application/x-www-form-urlencoded");
- xmlhttp.send();
- }
0 0