在现代软件开发中,将图像文件存储到数据库中是一个常见的需求。虽然互联网上关于这方面的信息很多,但实际的C++示例却寥寥无几。本文将展示如何使用ADO技术将图像文件存储到数据库中,以及如何从数据库中检索这些文件。这个过程不仅适用于图像文件,也适用于Word、Excel等其他文件格式。
本文提供的示例包含了两种方法:一种是从数据库中检索图像文件,另一种是将图像文件存储到数据库中。第一种方法从数据库中检索数据,然后在临时目录中创建一个文件,并将数据写入该文件。参数strImageName
是要创建的文件的名称,第二个参数是包含图像数据的ADO字段对象。
以下代码示例展示了如何从数据库中检索图像文件:
CString CADOImageDBDlg::GetImageFromADO(CString strImageName, FieldPtr pField)
{
// 创建临时文件
char tmpPath[_MAX_PATH+1];
GetTempPath(_MAX_PATH, tmpPath);
strImageName.Insert(0, tmpPath);
CFile outFile(strImageName, CFile::modeCreate | CFile::modeWrite);
// 辅助变量,用于检索图像数据
unsigned char* lpData = NULL;
long lngOffSet = 0;
long lngSize = pField->ActualSize;
const long ChunkSize = 50;
_variant_t varChunk;
UCHAR chData;
HRESULT hr;
long lBytesCopied = 0;
lpData = new unsigned char[lngSize];
// 从vararray中检索数据
while (lngOffSet < lngSize)
{
try
{
// 从数据库中获取50字节大小的数据块
varChunk = pField->GetChunk(ChunkSize);
// 将数据块放入safe array
for (long lIndex = 0; lIndex < ChunkSize - 1; lIndex++)
{
hr = SafeArrayGetElement(varChunk.parray, &lIndex, &chData);
if (SUCCEEDED(hr))
{
((UCHAR*)lpData)[lBytesCopied] = chData;
lBytesCopied++;
}
else
break;
}
lngOffSet += ChunkSize;
}
catch (_com_error &e)
{
dump_com_error(e);
return FALSE;
}
}
// 将数据写入文件
LPSTR buffer = (LPSTR)GlobalLock(lpData);
outFile.Write(lpData, lngSize);
GlobalUnlock(lpData);
delete lpData;
// 返回完整路径的文件
return strImageName;
}
bool CADOImageDBDlg::PutImageInADO(CString strFilePath, FieldPtr pFileData)
{
// 打开文件
CFile fileImage;
CFileStatus fileStatus;
fileImage.Open(strFilePath, CFile::modeRead);
fileImage.GetStatus(fileStatus);
// 分配内存以存储数据
ULONG nBytes = (ULONG)fileStatus.m_size;
HGLOBAL hGlobal = GlobalAlloc(GPTR, nBytes);
LPVOID lpData = GlobalLock(hGlobal);
// 将数据放入文件
fileImage.Read(lpData, nBytes);
HRESULT hr;
_variant_t varChunk;
long lngOffset = 0;
UCHAR chData;
SAFEARRAY FAR *psa = NULL;
SAFEARRAYBOUND rgsabound[1];
try
{
// 创建safe array以存储字节数组
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = nBytes;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
while (lngOffset < (long)nBytes)
{
chData = ((UCHAR*)lpData)[lngOffset];
hr = SafeArrayPutElement(psa, &lngOffset, &chData);
if (hr != S_OK)
return false;
lngOffset++;
}
lngOffset = 0;
// 将safe array分配给一个变量
varChunk.vt = VT_ARRAY | VT_UI1;
varChunk.parray = psa;
hr = pFileData->AppendChunk(varChunk);
if (hr != S_OK)
return false;
}
catch (_com_error &e)
{
dump_com_error(e);
return FALSE;
}
// 释放内存
GlobalUnlock(lpData);
return true;
}
为了显示图像,创建了一个类,该类封装了freeimage库。