Java向Mysql数据库中存储图片等二进制文件的实现,以及常见报错的解决!

Mysql数据库的功能很强大,除了能存储字符等常见数据以外,它同样可以存储图片等二进制文件,本文以存储照片为例。

一、Mysql存储二进制文件常见报错有:

1.com.mysql.jdbc.PacketTooBigException: Packet for query is too large问题。

这个问题是由于mysql数据库查询和接收包的数据大小有限制,默认是1M,当你存取的二进制文件比较大的时候你需要修改Mysql的配置,具体命令如下:

在mysql命令行中执行命令:

(1)首先查看当前配置。

show VARIABLES like '%max_allowed_packet%';

(2)修改最大可接收包大小为20M。 

set global max_allowed_packet = 2*1024*1024*10;

2.data too long for column 'xxx' at row 1问题 

这个问题是由于所存储的文件大于你所选择的二进制文件类型的最大长度,以图片存储为例一般选择BLOB类型,但是不同的blob类型有他的长度大小区分,具体如下:

BLOB是个类型系列,包括:TinyBlob、Blob、MediumBlob、LongBlob,这几个类型之间的唯一区别是在存储文件的最大大小上不同。 

BLOB类型

大小(单位:字节)

TinyBlob

最大255 byte

Blob

最大65 kb

MediumBlob

最大16 M

LongBlob

最大4 G


 二、下面贴上我写的数据库连接,二进制流的获取,图片存入和取出数据库的工具类,水平有限,有错误的地方请大家指正,共同学习。

我的mysql数据库表photo的设计如下 :

CREATE TABLE photo
(
  id    INT AUTO_INCREMENT
    PRIMARY KEY,
  name  VARCHAR(20) NOT NULL
  COMMENT '姓名',
  photo LONGBLOB    NOT NULL
  COMMENT '照片'
);

1.MysqlUtils工具类,用于数据库的连接和关闭。

package mydatabase;

import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * @date on 14:48 2018/8/16
 * @author yuyong
 * @describe 用于连接mysql数据库的工具类
 */
public class MysqlUtils {

    enum Constants{
        /**
         *定义枚举类型放入数据库连接的常量
         * Constants_Driver 驱动
         * Constants_Url 数据库路径
         * Constants_user 用户名
         * Constants_password 密码
         */
        Constants_Driver("com.mysql.jdbc.Driver"),
        Constants_Url("jdbc:mysql://localhost:3307/test"),
        Constants_user("root"),
        Constants_password("root");

        private String description;
        Constants (String description){
            this.description = description;
        }
        public String getDescription(){
            return description;
        }
    }

    static {
        try {
            Class.forName(Constants.Constants_Driver.getDescription());
            System.out.println("数据库驱动注册成功...");
        } catch (ClassNotFoundException e) {
            System.out.println("驱动注册失败");
            e.printStackTrace();
        }
    }

    /**
     * 获取数据库的连接
     * @return Connection
     */
    public static Connection getConnection(){
        try {
            Connection connection = DriverManager.getConnection(Constants.Constants_Url.getDescription(),
                    Constants.Constants_user.getDescription(),Constants.Constants_password.getDescription());
            System.out.println("数据库连接成功...");
            return connection;
        } catch (SQLException e) {
            System.out.println("获取连接失败");
            e.printStackTrace();
        }
        return null;
    }

    public static boolean closeConnection(Connection connection){
        if (null != connection){
            try {
                connection.close();
                System.out.println("数据库关闭成功...");
                return true;
            } catch (SQLException e) {
                System.out.println("关闭连接失败!!");
                e.printStackTrace();
            }
        }
        return false;
    }

    /**
     * Junit测试
     */
    @Test
    public void mysqlUtilsTest(){
        Connection connection = MysqlUtils.getConnection();
        MysqlUtils.closeConnection(connection);
    }

}

2. ReadImageUtils工具类,封装用于读取图片的工具流,用于数据库存储图片。

package mydatabase;

/**
 * @date on 15:15 2018/8/16
 * @author yuyong
 * @describe 封装用于读取图片的工具流,用于数据库存储图片
 */
import java.io.*;

public class ReadImageUtils {

    /**
     * 读取本地图片的输入流
     * @return FileInputStream
     */
    public static FileInputStream getIns(String imagePath){
        try {
            return new FileInputStream(new File(imagePath));
        } catch (FileNotFoundException e) {
            System.out.println("请检查文件路径是否正确");
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 读取数据库表中图片的输出流
     * @param targetPath 图片存储到本地的路径
     * @return FileOutputStream
     */
    public static FileOutputStream getOuts(String targetPath){
        File file = new File(targetPath);
        String path = targetPath.substring(0,targetPath.lastIndexOf("/"));
        //如果文件不存在则创建目录
        if (!file.exists()){
            new File(path).mkdir();
        }

        FileOutputStream fos ;
        try {
             fos = new FileOutputStream(file);
             return fos;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 读取数据库中的图片二进制数据写出目标地址
     * @param in 输入流
     * @param out 输出流
     * @return boolean
     */
    public static boolean readBinaryImage(InputStream in, OutputStream out){
        try {
            int len;
            byte[] b = new byte[1000];
            while ((len=in.read(b)) != -1){
                out.write(b,0,len);
            }
            out.flush();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (null != out){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != in){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return false;
    }
}

3. ImageSaveAndOut工具类,实现图片的本地与数据库传输。

 

package mydatabase;

/**
 * @date on 15:52 2018/8/16
 * @author yuyong
 * @describe 实现图片的本地与数据库传输!
 */
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class ImageSaveAndOut {


    /**
     * 存入和取出的sql语句
     */
    enum SQL{
        /**
         * SQL_IN 将图片存入数据库的sql语句
         * SQL_OUT 将图片从数据库取出的sql语句
         */
        SQL_IN("insert into photo (name,photo) values (?,?)"),
        SQL_OUT("select * from photo where id = ?");
        private String sql;
        SQL(String sql){
            this.sql = sql;
        }
        public String getSql(){
            return sql;
        }
    }
    private static PreparedStatement preparedStatement;
    private static ResultSet resultSet;
    private static Connection connection;
    private static InputStream in;
    private static OutputStream out;

    /**
     * 将图片资源存入数据库
     * @param imagePath 本地图片路径
     * @param name 名称
     * @return boolean
     */
    public static boolean imageToDatabase(String imagePath,String name){
        try {
            if (null == out){
                in = ReadImageUtils.getIns(imagePath);
            }
            connection = MysqlUtils.getConnection();
            if (null != connection) {
                preparedStatement = connection.prepareStatement(SQL.SQL_IN.getSql());
                //设置sql语句中的占位符?
                preparedStatement.setString(1,name);
                preparedStatement.setBlob(2,in,in.available());
                int count = preparedStatement.executeUpdate();
                if (count > 0){
                    System.out.println("存储图片成功...");
                    return true;
                }else {
                    System.out.println("存储图片失败...");
                    return false;
                }
            }
        }catch (SQLException | IOException e) {
            e.printStackTrace();
        } finally {
            MysqlUtils.closeConnection(connection);
            try {
                if (null != in ){
                    in.close();
                }
                if (null != preparedStatement){
                    preparedStatement.close();
                }
            }catch (IOException e) {
                System.out.println("输入流关闭失败...");
                e.printStackTrace();
            } catch (SQLException e) {
                System.out.println("预处理命令关闭失败...");
                e.printStackTrace();
            }
        }
        return true;
    }

    /**
     * 将数据库中的图片读出保存到本地
     * @param localPath 本地保存该图片的路径
     * @param id 数据库中该图片的id
     * @return boolean
     */
    public static boolean databaseToImage(String localPath, int id){
        try {

            connection = MysqlUtils.getConnection();
            if (null == out){
                out = ReadImageUtils.getOuts(localPath);
            }
            if (null != connection){
                preparedStatement = connection.prepareStatement(SQL.SQL_OUT.getSql());
            }
            preparedStatement.setInt(1,id);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()){
                in = resultSet.getBinaryStream("photo");
                ReadImageUtils.readBinaryImage(in,out);
                System.out.println("图片取出成功...");
            }
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            MysqlUtils.closeConnection(connection);
            if (null != resultSet){
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (null != preparedStatement){
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return false;
    }

    /**
     * Junit 测试
     */
    @Test
    public void imageSaveAndOutTest(){
        //存入
        //ImageSaveAndOut.imageToDatabase("./src/mydatabase/1111.jpg","yuyong");
        //取出
        ImageSaveAndOut.databaseToImage("./1.jpg",3);
    }
}

猜你喜欢

转载自blog.csdn.net/qingxixiansheng/article/details/81746216