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);
    }
}

 

要从数据库获取存储二进制文件,并还原为原始文件,可以使用以下步骤: 1.连接到数据库并执行查询以获取二进制数据。具体的查询语句将根据你的数据库系统和表结构而有所不同。 2.将查询结果二进制数据读取到一个字节数组。 3.使用字节数组来创建一个 ByteArrayInputStream 对象。 4.使用对象流来读取 ByteArrayInputStream 的数据,并将其写入到文件。 以下是一个 Java 代码示例,演示如何从数据库获取存储二进制文件,并将其读取到文件: ```java import java.io.ByteArrayInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.sql.*; public class BinaryFileReader { public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException { String url = "jdbc:mysql://localhost:3306/mydatabase"; String user = "root"; String password = "mypassword"; String sql = "SELECT file_data FROM mytable WHERE file_id = ?"; int fileId = 1; // replace with the file ID you want to retrieve try (Connection conn = DriverManager.getConnection(url, user, password); PreparedStatement stmt = conn.prepareStatement(sql)) { stmt.setInt(1, fileId); ResultSet rs = stmt.executeQuery(); if (rs.next()) { byte[] fileData = rs.getBytes("file_data"); try (ByteArrayInputStream bais = new ByteArrayInputStream(fileData); ObjectInputStream ois = new ObjectInputStream(bais); FileOutputStream fos = new FileOutputStream("my_file.jpg")) { byte[] buffer = new byte[1024]; int len; while ((len = ois.read(buffer)) != -1) { fos.write(buffer, 0, len); } } } else { System.out.println("File not found"); } } } } ``` 在这个示例,我们连接到一个名为 mydatabase 的 MySQL 数据库,并从名为 mytable 的表检索指定文件 ID 的二进制数据。我们使用 ResultSet 的 getBytes 方法将二进制数据读取到一个字节数组。接下来,我们使用 ByteArrayInputStream 创建一个输入流,并将字节数组作为构造函数的参数传入。然后,我们使用 ObjectInputStream 来读取 ByteArrayInputStream 的数据。最后,我们使用 FileOutputStream 将读取到的数据写入到一个文件。请注意,在这个示例,我假设我们要读取的文件是一个 JPEG 图像文件。如果你要读取的文件类型不同,则需要使用不同的文件扩展名。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值