Linux下實現MySQL存儲和提取圖片

 

前言:

   最近正好在項目中接觸到MySQL數據庫,無聊時候突然想把照片存儲到數據庫中,這一想法讓我不斷的查找資料和編寫代碼的實踐和測試下,今天最終在Linux下實現這一功能.

 

 //dbproc.c

/*************************************************************       
    FileName : dbproc.c   
    FileFunc : MySQL數據庫操作實現     
    Version  : V0.1       
    Author   : Sunrier       
    Date     : 2012-06-23 
    Descp    : Linux下使用C語言訪問MySQL函數        
*************************************************************/   
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>  
#include <mysql.h>

#define DEBUG        __FILE__,__LINE__


static MYSQL s_my_connection;
static int s_iDbconnected = 0; /*數據庫連接標誌 連接時爲1,斷開時爲0*/

/*程序調試函數*/
void debug(char *pFileName,int iLine,const char *fmt, ...)
{
	char szTemp[256];
	va_list vap;

	/*memset(szTemp,0,sizeof(szTemp));*/
	va_start(vap,fmt);
	fprintf(stderr,"[%s][%d]:",pFileName,iLine);
	memset(szTemp,0,sizeof(szTemp));
	vsprintf(szTemp,fmt,vap);
	va_end(vap);
	fprintf(stderr,"%s\n",szTemp);
	fflush(stderr);
}

/*測試MySQL客戶端版本*/
void mysql_version( void )  
{  
    printf("MySQL client version : %s ! \n",mysql_get_client_info());  
}  

/*登陸MySQL*/
int mysql_login(char* pServer,char *pUser,char *pPassword,char *pDataBase)
{
	MYSQL *conn_ptr = NULL;
	int iRetCode = -1;
	unsigned int uiTimeOut = 7;

	if( s_iDbconnected )
		return 0;
		
	conn_ptr = mysql_init(&s_my_connection);
	if( !conn_ptr )
	{
		fprintf(stderr,"mysql_init failed ! \n");
		return EXIT_FAILURE;
	}

	iRetCode = mysql_options(&s_my_connection,MYSQL_OPT_CONNECT_TIMEOUT,(const char *)&uiTimeOut);
	if( iRetCode  )
	{
		fprintf(stderr,"MySQL Connection is timeout! \n");
		return EXIT_FAILURE;
	}
	
	conn_ptr = NULL;
	conn_ptr = mysql_real_connect(&s_my_connection,pServer,pUser,pPassword,pDataBase,0,NULL,0);
	if( conn_ptr )
	{
		printf("MySQL Connection success!\n");
		s_iDbconnected = 1;		
	}
	else
	{
		fprintf(stderr,"MySQL Connection failed!\n");
		if( mysql_errno(&s_my_connection) )
		{
			fprintf(stderr,"Connection error %d: %s!\n",mysql_errno(&s_my_connection),mysql_error(&s_my_connection));
			return EXIT_FAILURE;
		}
	}
	
	return EXIT_SUCCESS;
}

/*退出MySQL*/
void mysql_logout( void )
{
	if( s_iDbconnected )
		mysql_close(&s_my_connection); /*關閉連接*/  
	s_iDbconnected = 0 ;
}

int mysql_proc( void )
{
	return 0;
}

/*向MySQL數據庫中存儲圖片*/
int mysql_store_image(char *pFileName,char *pImageTableName,unsigned char ucIdFlag,int iId)
{
	
	FILE *fp;
	char szImageName[31];
	char szImageData[1024*1000];/*圖片大小最大不超過1M*/
	char szStoreImageData[2*1024*1000+1];
	char szSql[2*1024*1000+1];
	unsigned long ulReadLength = 0,ulStoreLength = 0;
	int iRetCode = -1;
	
	
	fp = fopen(pFileName,"rb");
	
	if( NULL==fp )
	{	
		fprintf(stderr,"This file: [ %s ] isn't exsit !\n",pFileName);
		return EXIT_FAILURE;
	}
	
	memset(szImageData,0,sizeof(szImageData));
	ulReadLength = fread(szImageData,1,1024*1000,fp);
	fclose(fp);
	
	if( !ulReadLength )
	{	
		fprintf(stderr,"Read file found error !\n");		
		return EXIT_FAILURE;
	}

	printf("ulReadLength = %ld \n",ulReadLength);
	
	memset(szImageName,0,sizeof(szImageName));
	memcpy(szImageName,pFileName,strlen(pFileName));
	memset(szStoreImageData,0,sizeof(szStoreImageData));
	ulStoreLength = mysql_real_escape_string(&s_my_connection,szStoreImageData,szImageData,ulReadLength);
	/*二進制數據可能包含一些特殊字符,這些字符在sql語句中可能會引起一些問題,
	所以必須轉義,理論上每個字符都可能是特殊字符,所以szStoreImageData數組大小是szImageData數組大小的兩倍,
	該函數還會在szStoreImageData數組最後加上結尾符
	*/
	printf("ulStoreLength = %ld \n",ulStoreLength);
	
	memset(szSql,0,sizeof(szSql));
	if( 1==ucIdFlag )
	{
		sprintf(szSql,"insert into %s(id,name,data) values(%d,'%s','%s')",pImageTableName,iId,szImageName,szStoreImageData);
	}	
	else
	{
		sprintf(szSql,"insert into %s(name,data) values('%s','%s')",pImageTableName,szImageName,szStoreImageData);
	}
	
	iRetCode = mysql_query(&s_my_connection,szSql);
	if( iRetCode )
	{
		fprintf(stderr,"insert error ,sqlcode=[%d] : %s !\n",mysql_errno(&s_my_connection),mysql_error(&s_my_connection));
		return EXIT_FAILURE;
	}
	
	return EXIT_SUCCESS;		
	
}

/*向MySQL數據庫中存儲圖片*/
int mysql_store_image_ex(char *pFileName,char *pImageTableName,unsigned char ucIdFlag,int iId)
{
	FILE *fp;
	char szImageName[31];
	char szImageData[1024*1000];/*圖片大小最大不超過1M*/
	char szStoreImageData[2*1024*1000+1];
	char szSql[2*1024*1000+1];
	unsigned long ulReadLength = 0,ulStoreLength = 0,ulStoredLength = 0;
	int iRetCode = -1;
	
	fp = fopen(pFileName,"rb");
	if( NULL==fp )
	{	
		fprintf(stderr,"This file: [ %s ] isn't exsit !\n",pFileName);
		return EXIT_FAILURE;
	}
	
	memset(szImageData,0,sizeof(szImageData));
	ulReadLength = fread(szImageData,1,1024*1000,fp);
	fclose(fp);
	
	if( !ulReadLength )
	{	
		fprintf(stderr,"Read file found error !\n");		
		return EXIT_FAILURE;
	}

	printf("ulReadLength = %ld \n",ulReadLength);
	
	memset(szImageName,0,sizeof(szImageName));
	memcpy(szImageName,pFileName,strlen(pFileName));
	memset(szStoreImageData,0,sizeof(szStoreImageData));
	ulStoreLength = mysql_real_escape_string(&s_my_connection,szStoreImageData,szImageData,ulReadLength);
	/*二進制數據可能包含一些特殊字符,這些字符在sql語句中可能會引起一些問題,
	所以必須轉義,理論上每個字符都可能是特殊字符,所以szStoreImageData數組大小是szImageData數組大小的兩倍,
	該函數還會在szStoreImageData數組最後加上結尾符
	*/
	printf("ulStoreLength = %ld \n",ulStoreLength);
	
	memset(szSql,0,sizeof(szSql));
	if( 1==ucIdFlag )
	{
		sprintf(szSql,"insert into %s(id,name,data) values(%d,'%s','%s')",pImageTableName,iId,szImageName,szStoreImageData);
	}	
	else
	{
		sprintf(szSql,"insert into %s(name,data) values('%s','%s')",pImageTableName,szImageName,szStoreImageData);
	}
	
	ulStoredLength = strlen(szSql);
	iRetCode =  mysql_real_query(&s_my_connection,szSql,ulStoredLength);
	printf("ulStoredLength = %ld \n",ulStoredLength);
	if( iRetCode )
	{
		fprintf(stderr,"insert error ,sqlcode=[%d] : %s !\n",mysql_errno(&s_my_connection),mysql_error(&s_my_connection));
		return EXIT_FAILURE;
	}
	
	return EXIT_SUCCESS;		
	
}

/*從MySQL數據庫提取存儲的圖片*/
int mysql_fetch_image(char *pFileName,char *pImageTableName,unsigned char ucFlag,int iId)
{
	FILE *fp; 
	MYSQL_RES *res_ptr = NULL;
	MYSQL_ROW sqlrow;
	int iRetCode = -1,iTableRow = 0;
	char szSql[256];
	unsigned long *ulLength = NULL;
	unsigned long ulWriteLength = 0;

	/*
	ucFlag = 1 表示指定文件名
	*/
	memset(szSql,0,sizeof(szSql));
	if( 1==ucFlag )
	{	
		sprintf(szSql,"select data from %s where id = %d",pImageTableName,iId);
	}
	else
	{
		fprintf(stderr,"This flag [ %d ] found error for the filename ,and you must specify a filename !\n",ucFlag);
		return EXIT_FAILURE;
	}
	
	fp = fopen(pFileName,"wb");	
	if( NULL==fp )
	{	
		fprintf(stderr,"This file: [ %s ] isn't exsit !\n",pFileName);
		return EXIT_FAILURE;
	}
	
	iRetCode = mysql_query(&s_my_connection,szSql);	/*執行SQL語句*/
  	if( iRetCode )  
  	{  
		fprintf(stderr,"Select error %d: %s !\n",mysql_errno(&s_my_connection),mysql_error(&s_my_connection));	/*打印錯誤處理具體信息*/   
		return EXIT_FAILURE;  
	}  
	
	res_ptr = mysql_store_result(&s_my_connection);	/*集合*/
  	if( res_ptr )  
  	{  
  		iTableRow = mysql_num_rows(res_ptr);/*行*/
  	
	  	if( iTableRow==0 )/*表示查詢沒有結果*/
	  	{
	  		fclose(fp);
				fprintf(stderr,"Select data from %s where id = [ %d ] , result is null  !\n",pImageTableName,iId); 
				return EXIT_FAILURE;   
	  	}	
  	
	  	sqlrow = mysql_fetch_row(res_ptr); 
	  	ulLength = mysql_fetch_lengths(res_ptr); 

  		printf("ulFetchedLength: %ld\n",ulLength[0]);/*從數據庫中提取的數據信息長度*/

		mysql_free_result(res_ptr);	/*完成對數據的所有操作後,調用此函數來讓MySQL庫清理它分配的對象*/		
		
		ulWriteLength = fwrite(sqlrow[0],1,ulLength[0],fp);	
		if( ulWriteLength==0 )
		{	
			fclose(fp);
			fprintf(stderr,"Write file found error !\n");
			return EXIT_FAILURE;
		}
		printf("ulWriteLength = %ld \n",ulWriteLength);/*寫入文件的數據信息長度*/
		
	}
	else  
  	{ 
  		fclose(fp);
		fprintf(stderr,"Select result is null  !\n"); 
		return EXIT_FAILURE;   
  	}  
  
 	fclose(fp);
	return EXIT_SUCCESS;
}

/*從MySQL數據庫提取存儲的圖片*/
int mysql_fetch_image_ex(char *pFileName,char *pImageTableName,unsigned char ucFlag,int iId)
{
	FILE *fp; 
	MYSQL_RES *res_ptr = NULL;
	MYSQL_ROW sqlrow;
	int iRetCode = -1,iTableRow = 0;
	char szSql[256];
	unsigned long *ulLength = NULL;
	unsigned long ulWriteLength = 0;


	memset(szSql,0,sizeof(szSql));
	
	/*
		ucFlag = 2 表示取數據庫表中的信息文件名
	*/	
	if( 2==ucFlag )
	{	
		sprintf(szSql,"select data,name from %s where id = %d",pImageTableName,iId);
	}
	else
	{
		fprintf(stderr,"This flag [ %d ] found error for the filename ,and you needn't specify a filename !\n",ucFlag);
		return EXIT_FAILURE;
	}
			
	iRetCode = mysql_query(&s_my_connection,szSql);	/*執行SQL語句*/
  	if( iRetCode )  
  	{  
		fprintf(stderr,"Select error %d: %s !\n",mysql_errno(&s_my_connection),mysql_error(&s_my_connection));	/*打印錯誤處理具體信息*/   
		return EXIT_FAILURE;  
	}  
	
	res_ptr = mysql_store_result(&s_my_connection);	/*集合*/
  	if( res_ptr )  
  	{  
	  	iTableRow = mysql_num_rows(res_ptr);/*行*/
	  	
	  	if( iTableRow==0 )/*表示查詢沒有結果*/
	  	{
	  		fclose(fp);
				fprintf(stderr,"Select data,name from %s where id = [ %d ] , result is null  !\n",pImageTableName,iId); 
				return EXIT_FAILURE;   
	  	}	
  	
	  	sqlrow = mysql_fetch_row(res_ptr); 
	  	ulLength = mysql_fetch_lengths(res_ptr); 
	  	sscanf(sqlrow[1],"%s",pFileName);/*從數據庫中取文件名*/

	  	printf("ulFetchedLength: %ld\n",ulLength[0]);

		mysql_free_result(res_ptr);	/*完成對數據的所有操作後,調用此函數來讓MySQL庫清理它分配的對象*/	
		
		fp = fopen(pFileName,"wb");	
		if( NULL==fp )
		{	
			fprintf(stderr,"This file: [ %s ] isn't exsit !\n",pFileName);
			return EXIT_FAILURE;
		}
		
		ulWriteLength = fwrite(sqlrow[0],1,ulLength[0],fp);	
		if( ulWriteLength==0 )
		{	
			fclose(fp);
			fprintf(stderr,"Write file found error !\n");
			return EXIT_FAILURE;
		}
		printf("ulWriteLength = %ld \n",ulWriteLength);
		
	}
	else  
  	{ 
  		fclose(fp);
		fprintf(stderr,"Select result is null  !\n"); 
		return EXIT_FAILURE;   
  	}  
  
  	fclose(fp);
	return EXIT_SUCCESS;
}



 

 

//store.c

/***********************************************************************       
    FileName : store.c   
    FileFunc : 把圖片存儲到MySQL數據庫中操作測試(圖片大小最大不超過1M)     
    Version  : V0.1       
    Author   : Sunrier       
    Date     : 2012-06-23 
    Descp    : Linux下使用C語言訪問MySQL函數        
************************************************************************/
#include <stdio.h>

int main(int argc,char *argv[])
{ 
	char szServer[20] = "localhost"; /*127.0.0.1*/ 
	char szUser[20] = "Sunrier";  
	char szPassword[20] = "redhat";  
	char szDatabase[20] = "test"; 
	char szFileName[30],szTableName[30];
	unsigned char ucIdFlag = 0;/*手動插入ID標誌*/
	int iRetCode = -1,iId =0;
      
  	iRetCode = mysql_login(szServer,szUser,szPassword,szDatabase);  	
	if( iRetCode )
	{
		return 1;
	}
	
	memset(szFileName,0,sizeof(szFileName));	
	memset(szTableName,0,sizeof(szTableName));	
	strcpy(szFileName,"Sunrier.jpg");
	strcpy(szTableName,"images");
	ucIdFlag = 0;
	iId =1;
	
	/*iRetCode = mysql_store_image( szFileName,szTableName,ucIdFlag,iId );*/
	iRetCode = mysql_store_image_ex( szFileName,szTableName,ucIdFlag,iId );
	if( !iRetCode )
	{	
		fprintf(stderr,"Image has been stored in the database !\n");
	}
	
	mysql_logout();
	
	return 0;
}  




 

 

//fetch.c

/**********************************************************************       
    FileName : fetch.c   
    FileFunc : 從MySQL數據庫中提取圖片操作測試(圖片大小最大不超過1M)       
    Version  : V0.1       
    Author   : Sunrier       
    Date     : 2012-06-23 
    Descp    : Linux下使用C語言訪問MySQL函數        
***********************************************************************/
#include <stdio.h>

int main(int argc,char *argv[])
{
	int iRetCode = -1;  
	char szServer[20] = "localhost";  
	char szUser[20] = "Sunrier";  
	char szPassword[20] = "redhat";  
	char szDatabase[20] = "test"; 
 	char szFileName[30],szTableName[30];
 	unsigned char ucFlag = 0;
  	int iId = 0;
      
  	iRetCode = mysql_login(szServer,szUser,szPassword,szDatabase);  
	
	if( iRetCode )
	{
		return 1;
	}
	
	ucFlag = 2;
	iId = 9;
	memset(szFileName,0,sizeof(szFileName));	
	memset(szTableName,0,sizeof(szTableName));
	strcpy(szFileName,"Sunrier.jpg");
	strcpy(szTableName,"images");
	/*iRetCode = mysql_fetch_image(szFileName,szTableName,ucFlag,iId);*/
	iRetCode = mysql_fetch_image_ex(szFileName,szTableName,ucFlag,iId);
	if( !iRetCode )
	{	
		fprintf(stderr,"Image has been fetched from the database !\n");
	}
	
	mysql_logout();
	
	return 0;
}  



 

 

//makefile

#makefile
OBJS = store fetch   
all:$(OBJS)  
CFLAGS = -O -w -ansi     
#CFLAGS = -O -Wall -ansi    
CC = gcc $(CFLAGS)
MYSQLINCPATH = -I/usr/include/mysql  
MYSQLLIBPATH = -L/usr/lib/mysql  
MYSQLLIB = -lmysqlclient -lz -lm

store:store.c dbproc.c 
	@$(CC) $(MYSQLINCPATH) $(MYSQLLIBPATH) -o $@ $? $(MYSQLLIB)
fetch:fetch.c dbproc.c 
	@$(CC) $(MYSQLINCPATH) $(MYSQLLIBPATH) -o $@ $? $(MYSQLLIB)	
clean:
	@ls | grep -v ^makefile$$ | grep -v [.]c$$ | grep -v [.]h$$ | grep -v [.]sql$$ | grep -v [.]jpg$$ | grep -v [.]txt$$ | xargs rm -rf
#makefile


 

 

//images.sql

drop database if exists test;  
create database test;  
use test;  
create table images  
(  
    id integer auto_increment not null primary key, 
    name varchar(30) not null, 
    data mediumblob not null
); 

-- )engine=innodb charset=gb2312; -- 指定引擎和編碼方式
-- 圖片是二進制數據,mysql有種特殊的數據類型,用來存儲二進制數據,叫做BLOB(Binary Large Ojbect) 



 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章