MYSQL数据库存取图片等文件(C语言)

直接把文件放入数据库中比较适合小文件,方便管理,比如头像图片和声音,如果是较大型的文件建议不要直接存进数据库,而是放在服务器,把文件索引放在数据库。

MYSQL 中有个数据对象是 BLOB,即 Binary Large Object,顾名思义也就是二进制大型数据对象,用来记录二进制的数据,它有 4 种类型,分别是:tinyblob(255B)、blob(65KB)、mediumblob(16MB)、longblob(4GB)。

我在数据库中创建了一张 images 表,如下图:


先把用到的头文件和预处理写一下:

#include <winsock.h>
#include <mysql.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#pragma comment(lib, "libmysql.lib")
#define BYTE unsigned char
#define FILE_MAX_SIZE (65 * 1024) /*文件最大65KB*/

接下来的任务就是怎么把数据记录到 img 字段,我用C语言写了个函数,函数接受文件路径:

void insert(char *path)
{
	FILE *fp;
	BYTE *img, data;
	long cnt = 0;
	MYSQL mysql;
	char *sql;

	/*读取文件*/
	fp = fopen(path, "rb");
	if (!fp)
	{
		printf("读取文件失败\n");
		return;
	}
	img = malloc(FILE_MAX_SIZE); //分配65KB的内存
	memset(img, FILE_MAX_SIZE, 0);
	while (!feof(fp))
	{
		fread(&data, 1, 1, fp);
		if (data == '\0') //将结束字符转义
		{
			img[cnt++] = '\\';
			img[cnt++] = '0';
			continue;
		}
		if (data == '\'' || data == '\\' /*|| data == '\"'*/) //这些字符也要转义
		{
			img[cnt++] = '\\';
		}
		img[cnt++] = data;
		if (cnt == FILE_MAX_SIZE)
		{
			printf("文件超过65KB\n");
			free(img);
			fclose(fp);
			return;
		}
	}
	img[cnt] = '\0';
	fclose(fp);
	

	/*操作数据库*/
	if (NULL == mysql_init(&mysql))
	{
		printf("初始化数据库失败\n");
		return;
	}
	if (NULL == mysql_real_connect(&mysql, "localhost", "root", "password", "test", 0, NULL, 0))
	{
		printf("连接数据库失败\n");
		return;
	}

	sql = malloc(126 + FILE_MAX_SIZE);
	memset(sql, 126 + FILE_MAX_SIZE, 0);
	sprintf(sql, "INSERT INTO images (img) VALUES ('%s')", img);
	if (0 != mysql_real_query(&mysql, sql, strlen(sql)))
	{
		printf("执行SQL语句出错\n");
		mysql_close(&mysql);
		free(sql);
		free(img);
		return;
	}
	mysql_close(&mysql);
	free(sql);
	free(img);
	printf("插入成功\n");
}

从以上代码可以看出整个过程是将文件以二进制形式读出,然后再执行 SQL 语句。


下面我要将文件从数据库中读取出来,存放本地,该函数结束文件路径和在数据库中的 id 字段:

void peek(char *filename, int id)
{
	MYSQL mysql;
	FILE *fp;
	char sql[126];
	MYSQL_RES *res;
	MYSQL_ROW row;
	long *length;

	/*操作数据库*/
	if (NULL == mysql_init(&mysql))
	{
		printf("初始化数据库失败\n");
		return;
	}
	if (NULL == mysql_real_connect(&mysql, "localhost", "root", "password", "test", 0, NULL, 0))
	{
		printf("连接数据库失败\n");
		return;
	}

	sprintf(sql, "SELECT img FROM images WHERE id=%d", id);
	if (0 != mysql_real_query(&mysql, sql, strlen(sql)))
	{
		printf("执行SQL语句出错\n");
	}

	res = mysql_store_result(&mysql);
	if (NULL == res)
	{
		printf("数据库中无结果\n");
		mysql_close(&mysql);
	}
	row = mysql_fetch_row(res);
	length = mysql_fetch_lengths(res); //得到img字段数据的长度

	mysql_close(&mysql);

	/*写入文件*/
	fp = fopen(filename, "wb");
	if (!fp)
	{
		mysql_free_result(res);
		mysql_close(&mysql);
		printf("创建文件失败\n");
		return;
	}
	fwrite(row[0], 1, length[0], fp); //这里千万不能用strlen计算长度,因为文件中可能有很多结束标志字符'\0'
	fclose(fp);
	mysql_free_result(res);
	mysql_close(&mysql);
	printf("读取成功\n");
}


我开始被 strlen 的问题搞得晕头转向,心想不用 strlen 那我再用什么得到长度呢,还好后来找到了 mysql_fetch_lengths 这个函数。



  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值