在实际的开发中,我们可能需要将图片、影音等文件直接保存到数据库中,然后通过编程方式将数据读出进行使用。例如将读出的图片数据显示出来,将读出的电影文件播放出来。

二进制数据直接保存到文件和从文件中读出非常的简单。和普通的数据库操作差别不大。只是用到部分流操作。例如各种输入输出流操作。所以深刻理解流操是非常重要的。

在此我借助于一个JSP的简单实例进行讲解。此实例保存职员数据,其中职员数据包含一个图片列。此列保存每名员工的照片。在此将照片直接保存到数据库中。首先建立职员信息表EmployeeInfo,表列非常的简单

employeeId:职员编号(自动增长);employeeName:职员姓名;age:职员年龄;pic:职员图片(image类型)

首先讲解信息的保存。先建立一个录入界面index.jsp,其中包含一个<input type="file"/>元素,用于让用户选择图片文件。

页面代码如下(不做过多讲解):

 1 <%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
 2 <%
 3 String path = request.getContextPath();
 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 5 %>
 6 
 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 8 <html>
 9   <head>
10     <base href="<%=basePath%>">
11     
12     <title>My JSP 'index.jsp' starting page</title>
13  <meta http-equiv="pragma" content="no-cache">
14  <meta http-equiv="cache-control" content="no-cache">
15  <meta http-equiv="expires" content="0">    
16  <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
17  <meta http-equiv="description" content="This is my page">
18  <!--
19  <link rel="stylesheet" type="text/css" href="styles.css">
20  -->
21   </head>
22   
23   <body>
24     <form action="addServlet" method="POST">
25      <table border="15" width="60%" align="center">
26       <tr>
27        <td width="30%" align="right">EmployeeName:</td>
28        <td width="70%" align="left"><input type="text" name="employeeName"/></td>
29       </tr>
30       <tr>
31        <td width="30%" align="right">Age:</td>
32        <td width="70%" align="left"><input type="text" name="age"/></td>
33       </tr>
34       <tr>
35        <td width="30%" align="right">Image:</td>
36        <td width="70%" align="left"><input type="file" name="pic"/></td>
37       </tr>
38       <tr>
39        <td colspan="2" align="center"><input type="submit" value="add"/></td>
40       </tr>      
41      </table>
42     </form>
43   </body>
44 </html>
index.jsp

页面请求addServlet,获取录入信息,并调用JavaBean实现数据保存。Servlet代码如下:

 1 import java.io.IOException;
 2 import java.io.PrintWriter;
 3 
 4 import javax.servlet.ServletException;
 5 import javax.servlet.http.HttpServlet;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 import com.frank.rule.*;
 9 public class AddServlet extends HttpServlet {
10 
11  /**
12   * Constructor of the object.
13   */
14  public AddServlet() {
15   super();
16  }
17 
18  /**
19   * Destruction of the servlet. <br>
20   */
21  public void destroy() {
22   super.destroy(); // Just puts "destroy" string in log
23   // Put your code here
24  }
25 
26  /**
27   * The doGet method of the servlet. <br>
28   *
29   * This method is called when a form has its tag value method equals to get.
30   * 
31   * @param request the request send by the client to the server
32   * @param response the response send by the server to the client
33   * @throws ServletException if an error occurred
34   * @throws IOException if an error occurred
35   */
36  public void doGet(HttpServletRequest request, HttpServletResponse response)
37    throws ServletException, IOException {
38 
39   String employeeName=request.getParameter("employeeName");
40   int age=Integer.parseInt(request.getParameter("age"));
41   String pic=request.getParameter("pic");
42   EmployeeDAO employeeDAO=new EmployeeDAO();
43   if(employeeDAO.employeeAdd(employeeName, age, pic))
44    response.sendRedirect("success.jsp");
45   else
46    response.sendRedirect("index.jsp");
47   
48  }
49 
50  /**
51   * The doPost method of the servlet. <br>
52   *
53   * This method is called when a form has its tag value method equals to post.
54   * 
55   * @param request the request send by the client to the server
56   * @param response the response send by the server to the client
57   * @throws ServletException if an error occurred
58   * @throws IOException if an error occurred
59   */
60  public void doPost(HttpServletRequest request, HttpServletResponse response)
61    throws ServletException, IOException {
62 
63   doGet(request,response);
64  }
65 
66  /**
67   * Initialization of the servlet. <br>
68   *
69   * @throws ServletException if an error occurs
70   */
71  public void init() throws ServletException {
72   // Put your code here
73  }
74 
75 }
AddServlet

此Servlet只是简单的获取页面输入的数据,其中获取的Pic为用户选择的图片路径。严格讲,获取文件需要经过验证,防止非法图片的选择,这个可以根据自己的需要改善。然后Servlet调用业务类,将获取的数据通过参数传入,进行数据的增加。其中employeeAdd方法实现数据的保存,代码如下:

 1 public boolean employeeAdd(String employeeName,int age,String pic){
 2   Connection conn=null;
 3   PreparedStatement pstmt=null;
 4   FileInputStream fis=null;
 5   try{
 6    Class.forName("net.sourceforge.jtds.jdbc.Driver");
 7    conn=DriverManager.getConnection("jdbc:jtds:sqlserver://localhost:1433/SampleDB","sa","");
 8    fis=new FileInputStream(pic);
 9    
10    String strSQL="INSERT INTO employeeInfo VALUES(?,?,?)";
11    pstmt=conn.prepareStatement(strSQL);
12    pstmt.setString(1, employeeName);
13    pstmt.setInt(2, age);
14    pstmt.setBinaryStream(3, fis, fis.available());
15    if(pstmt.executeUpdate()>0)
16     return true;
17    else
18     return false;
19   }catch(ClassNotFoundException ex){
20    ex.printStackTrace();
21    return false;
22   }catch(SQLException ex){
23    ex.printStackTrace();
24    return false;
25   }catch(IOException ex){
26    ex.printStackTrace();
27    return false;
28   }finally{
29    try{
30     fis.close();
31     pstmt.close();
32     conn.close();
33    }catch(Exception ex){
34     
35    }
36   }
37  }
employeeAdd

注意粗体部分,用获取的pic信息(文件路径)创建文件输入流对象,增加pic字段的内容通过流对象增加。

pstmt.setBinaryStream(3, fis, fis.available());
三个参数分别为:参数索引,流对象,流对象大小

当增加成功时,重定向到success.jsp

运行结果如下:

 

增加后,显示如下代表成功:

 

那么如何验证图片数据是否保存到了数据库中呢?我们通过再次检索增加的数据,读出增加的图片数据并在页面中显示出来进行验证。

首先建立一个非常简单的页面search.jsp,此页面通过文本框使用户输入要检索的人员的姓名,检索人员的基本信息(不检索图片数据),将检索的人员数据形成JOPO对象,保存到session中,以便页面使用。

POJO类(EmployeeObj)

 1 public class EmployeeObj {
 2  private int employeeId;
 3  private String employeeName;
 4  private int age;
 5  public int getEmployeeId() {
 6   return employeeId;
 7  }
 8  public void setEmployeeId(int employeeId) {
 9   this.employeeId = employeeId;
10  }
11  public String getEmployeeName() {
12   return employeeName;
13  }
14  public void setEmployeeName(String employeeName) {
15   this.employeeName = employeeName;
16  }
17  public int getAge() {
18   return age;
19  }
20  public void setAge(int age) {
21   this.age = age;
22  }
23  
24 }
EmployeeObj

search.jsp页面代码如下:

 1 <%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
 2 <%
 3 String path = request.getContextPath();
 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 5 %>
 6 
 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 8 <html>
 9   <head>
10     <base href="<%=basePath%>">
11     
12     <title>My JSP 'search.jsp' starting page</title>
13     
14  <meta http-equiv="pragma" content="no-cache">
15  <meta http-equiv="cache-control" content="no-cache">
16  <meta http-equiv="expires" content="0">    
17  <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
18  <meta http-equiv="description" content="This is my page">
19  <!--
20  <link rel="stylesheet" type="text/css" href="styles.css">
21  -->
22 
23   </head>
24   
25   <body>
26     <form action="searchServlet" method="POST">
27      employeeName:<input type="text" name="employeeName"/>
28      <input type="submit" value="search"/>
29     </form>
30   </body>
31 </html>
search.jsp

通过searchServlet实现基本信息的检索

 1 import java.io.IOException;
 2 import java.io.PrintWriter;
 3 
 4 import javax.servlet.ServletException;
 5 import javax.servlet.http.HttpServlet;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 import javax.servlet.http.HttpSession;
 9 
10 public class SearchServlet extends HttpServlet {
11 
12  /**
13   * Constructor of the object.
14   */
15  public SearchServlet() {
16   super();
17  }
18 
19  /**
20   * Destruction of the servlet. <br>
21   */
22  public void destroy() {
23   super.destroy(); // Just puts "destroy" string in log
24   // Put your code here
25  }
26 
27  /**
28   * The doGet method of the servlet. <br>
29   *
30   * This method is called when a form has its tag value method equals to get.
31   * 
32   * @param request the request send by the client to the server
33   * @param response the response send by the server to the client
34   * @throws ServletException if an error occurred
35   * @throws IOException if an error occurred
36   */
37  public void doGet(HttpServletRequest request, HttpServletResponse response)
38    throws ServletException, IOException {
39 
40   String employeeName=request.getParameter("employeeName");
41   EmployeeDAO employeeDAO=new EmployeeDAO();
42   EmployeeObj employeeObj=employeeDAO.getEmployeeByName(employeeName);
43   HttpSession session=request.getSession();
44   session.setAttribute("employee", employeeObj);
45   response.sendRedirect("display.jsp");
46  }
47 
48  /**
49   * The doPost method of the servlet. <br>
50   *
51   * This method is called when a form has its tag value method equals to post.
52   * 
53   * @param request the request send by the client to the server
54   * @param response the response send by the server to the client
55   * @throws ServletException if an error occurred
56   * @throws IOException if an error occurred
57   */
58  public void doPost(HttpServletRequest request, HttpServletResponse response)
59    throws ServletException, IOException {
60 
61   doGet(request,response);
62  }
63 
64  /**
65   * Initialization of the servlet. <br>
66   *
67   * @throws ServletException if an error occurs
68   */
69  public void init() throws ServletException {
70   // Put your code here
71  }
72 
73 }
SearchServlet

此Servlet调用业务类的getEmployeeByName方法检索人员基本信息,返回EmployeeObj对象,并放入session中,当然也可以放入request中,根据自己的需要改进。页面检索成功后重定向到display.jsp进行信息的显示(稍后讲解)

getEmployeeByName方法代码如下:

 1 public EmployeeObj getEmployeeByName(String employeeName){
 2   Connection conn=null;
 3   PreparedStatement pstmt=null;
 4   ResultSet rst=null;
 5   EmployeeObj employeeObj=new EmployeeObj();
 6   try{
 7    Class.forName("net.sourceforge.jtds.jdbc.Driver");
 8    conn=DriverManager.getConnection("jdbc:jtds:sqlserver://localhost:1433/SampleDB","sa","");
 9    
10    String strSQL="SELECT employeeId,employeeName,age FROM EmployeeInfo WHERE employeeName=?";
11    pstmt=conn.prepareStatement(strSQL);
12    pstmt.setString(1, employeeName);
13    rst=pstmt.executeQuery();
14    if(rst.next()){
15     employeeObj.setEmployeeId(rst.getInt("employeeId"));
16     employeeObj.setEmployeeName(rst.getString("employeeName"));
17     employeeObj.setAge(rst.getInt("age"));
18     return employeeObj;
19    }
20    return null;
21   }catch(ClassNotFoundException ex){
22    ex.printStackTrace();
23    return null;
24   }catch(SQLException ex){
25    ex.printStackTrace();
26    return null;
27   }finally{
28    try{
29     pstmt.close();
30     conn.close();
31    }catch(Exception ex){
32     
33    }
34   }
35  } 
getEmployeeByName

display.jsp负责显示查询出的结果信息,代码如下:

 1 <%@ page language="java" import="java.util.*,com.frank.obj.*" pageEncoding="ISO-8859-1"%>
 2 <%
 3 String path = request.getContextPath();
 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 5 %>
 6 
 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 8 <html>
 9   <head>
10     <base href="<%=basePath%>">
11     
12     <title>My JSP 'display.jsp' starting page</title>
13     
14  <meta http-equiv="pragma" content="no-cache">
15  <meta http-equiv="cache-control" content="no-cache">
16  <meta http-equiv="expires" content="0">    
17  <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
18  <meta http-equiv="description" content="This is my page">
19  <!--
20  <link rel="stylesheet" type="text/css" href="styles.css">
21  -->
22  <%
23   EmployeeObj employeeObj=(EmployeeObj)session.getAttribute("employee");
24   %>
25   </head>
26   
27   <body>
28     <table width="80" border="15">
29      <tr>
30       <td width="30%" align="right">EmployeeId</td>
31       <td width="70%" align="left"><%=employeeObj.getEmployeeId() %></td>
32      </tr>
33      <tr>
34       <td width="30%" align="right">EmployeeName</td>
35       <td width="70%" align="left"><%=employeeObj.getEmployeeName() %></td>
36      </tr>
37      <tr>
38       <td width="30%" align="right">Age</td>
39       <td width="70%" align="left"><%=employeeObj.getAge() %></td>
40      </tr>
41      <tr>
42       <td width="30%" align="right">Pic</td>
43       <td width="70%" align="left"><img src="displayServlet?employeeId=<%=employeeObj.getEmployeeId() %>"/></td>
44      </tr>     
45     </table>
46   </body>
47 </html>
display.jsp

代码非常的简单,只是简单的从session中获取保存的EmployeeObj对象,然后利用jsp表达式将数据成员信息显示到页面上。但是注意粗体部分,因为我们需要将保存的图片数据读出,然后显示成图片。所以在此我们利用Img元素显示图片,而Src利用displayServlet的运行结果输出到客户端,作为图片的显示源。displayServlet包含参数employeeId,用来决定具体显示哪一员工的图片。

displayServlet通过Servlet输出流,将读取的图片数据发送到客户端,代码如下:

 1 import java.awt.image.BufferedImage;
 2 import java.io.IOException;
 3 import java.io.InputStream;
 4 import java.io.PrintWriter;
 5 
 6 import javax.imageio.ImageIO;
 7 import javax.servlet.ServletException;
 8 import javax.servlet.ServletOutputStream;
 9 import javax.servlet.http.HttpServlet;
10 import javax.servlet.http.HttpServletRequest;
11 import javax.servlet.http.HttpServletResponse;
12 
13 import com.frank.rule.EmployeeDAO;
14 
15 public class DisplayServlet extends HttpServlet {
16 
17  /**
18   * Constructor of the object.
19   */
20  public DisplayServlet() {
21   super();
22  }
23 
24  /**
25   * Destruction of the servlet. <br>
26   */
27  public void destroy() {
28   super.destroy(); // Just puts "destroy" string in log
29   // Put your code here
30  }
31 
32  /**
33   * The doGet method of the servlet. <br>
34   *
35   * This method is called when a form has its tag value method equals to get.
36   * 
37   * @param request the request send by the client to the server
38   * @param response the response send by the server to the client
39   * @throws ServletException if an error occurred
40   * @throws IOException if an error occurred
41   */
42  public void doGet(HttpServletRequest request, HttpServletResponse response)
43    throws ServletException, IOException {
44   
45   response.setContentType("image/gif");
46   int employeeId=Integer.parseInt(request.getParameter("employeeId"));
47   EmployeeDAO employeeDAO=new EmployeeDAO();
48   InputStream is=employeeDAO.getPicById(employeeId);
49   int size=is.available();
50   byte[] image=new byte[size];
51   is.read(image);
52   ServletOutputStream out=response.getOutputStream();
53   out.write(image);
54   
55  }
56 
57  /**
58   * Initialization of the servlet. <br>
59   *
60   * @throws ServletException if an error occurs
61   */
62  public void init() throws ServletException {
63   // Put your code here
64  }
65 
66 }
DisplayServlet

在此,调用业务类的getPicById方法得到图片数据的输入流。然后获取的输入流写到ServletOutputStream,这样可以在Servlet的输出端使用,即img的src中使用

getPicById代码如下:

 1 public InputStream getPicById(int employeeId){
 2   Connection conn=null;
 3   PreparedStatement pstmt=null;
 4   ResultSet rst=null;
 5   InputStream is=null;
 6   try{
 7    Class.forName("net.sourceforge.jtds.jdbc.Driver");
 8    conn=DriverManager.getConnection("jdbc:jtds:sqlserver://localhost:1433/SampleDB","sa","");
 9    
10    String strSQL="SELECT pic FROM EmployeeInfo WHERE employeeId=?";
11    pstmt=conn.prepareStatement(strSQL);
12    pstmt.setInt(1, employeeId);
13    rst=pstmt.executeQuery();
14    if(rst.next()){
15     is=rst.getBinaryStream("pic");
16     return is;
17    }
18    return null;
19   }catch(ClassNotFoundException ex){
20    ex.printStackTrace();
21    return null;
22   }catch(SQLException ex){
23    ex.printStackTrace();
24    return null;
25   }finally{
26    try{
27     pstmt.close();
28     conn.close();
29    }catch(Exception ex){
30     
31    }
32   }
33  } 
getPicById

注意粗体部分

好了,我们可以通过运行结果来进行验证,假设我们搜索名称为Mike的人员数据,那么这样:

 

点search按钮,运行结果如下:

好了,显示出了检索结果,不但包括人员的基本数据,保存到数据库中的图片数据也被读出并显示成图片。

代码只是利用jsp简单的进行体现,大家可以根据自己的需要进行改进。