把图片存/取至数据库

http://blog.chinaunix.net/uid-607545-id-2088102.html

http://blog.csdn.net/eryadabendan/article/details/6749939

关于图片的存储和显示 

第一步:首先是要打开一个位图文件,这里使用的控件用Picture控件,就是控件图标右边最上面那个,改ID号为IDC_PICTURE,然后定义两个成员变量

char *m_char;//图片文件指针
DWORD m_nFileLen;//图片长度
然后在函数中写入:
CFileDialog dlg(TRUE,NULL,NULL,0,"photo Files (*.jpg;*.bmp)|*.jpg;*.bmp|",this);
   if(IDOK==dlg.DoModal()) 
{
   m_path=dlg.GetPathName();
   m_bool=true;
}
   CWnd *pWnd = GetDlgItem(IDC_PICTURE); 
   CRect rect; 
   pWnd->GetClientRect(&rect); 
   CDC *pDC = pWnd->GetDC(); 
   CFileStatus fstatus; 
   CFile file; 
   LONG cb; 
   BOOL m_tm=false;
   IPicture *pPic; 
   CString m_sPath; 
   if (file.Open(m_path,CFile::modeRead)&& file.GetStatus(m_path,fstatus)&&((cb = fstatus.m_size) != -1))   
   {
   
   if(cb>1048576)   //可在此设置图片大小
   {
     m_tm=false;
     MessageBox("图片不能大于1M","提示!");
   }
   else
   {
    
     m_nFileLen=(UINT)cb;        
     HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb); 
     LPVOID pvData = NULL; 
     if (hGlobal != NULL) 
     { 
     if ((pvData = GlobalLock(hGlobal)) != NULL) 
     { 
       file.ReadHuge(pvData, cb); 
       m_char=(char*)pvData;
       GlobalUnlock(hGlobal); 
       CreateStreamOnHGlobal(hGlobal, TRUE, &pStm); 
       m_tm=true;
       // m_bool=true;
     } 
     else
       AfxMessageBox("不是图片文件!");
     } 
     else
     AfxMessageBox("申请内存失败!");
    
   }
   }  
   else
   AfxMessageBox("不是图片文件!");
   if(m_tm) 
   { 
   SUCCEEDED(OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic));
   OLE_XSIZE_HIMETRIC hmWidth; 
   OLE_YSIZE_HIMETRIC hmHeight; 
   pPic->get_Width(&hmWidth); 
   pPic->get_Height(&hmHeight);   
   if(FAILED(pPic->Render(*pDC,0,0,rect.Width(),rect.Height(),0,hmHeight,hmWidth,-hmHeight,NULL))) 
     AfxMessageBox("渲染图像失败!"); 
   pPic->Release(); 
   }
这里还有个小小的问题,就是当窗口出现重画的时候图片就会消失,可以把上面的代码加入到OnPaint函数中去;
接来就是保存文件(怎么访问数据库的可以去看下我空间里的"用ADO访问数据库"):
在Access数据库中把要放相片字段的类型改为OLE 类型(在SQL数据库改成相片类型).
m_RecordSet->AddNew();
char   *pBuf = m_char;//把图片的指针传给pBuf
   VARIANT   varBLOB;
   SAFEARRAY   *psa;
   SAFEARRAYBOUND rgsabound[1];
   if(pBuf)
   {    
   rgsabound[0].lLbound = 0;
   rgsabound[0].cElements = m_nFileLen;
   psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
   for (long i = 0; i < (long)m_nFileLen; i++)
     SafeArrayPutElement (psa, &i, pBuf++);
   varBLOB.vt = VT_ARRAY | VT_UI1;
   varBLOB.parray = psa;
   m_pRecordset->GetFields()->GetItem("读者相片")->AppendChunk(varBLOB);      
   }
   m_pRecordset->Update();


接下来就是把图片从数据库中取出来,在放图相的对话框中加入Picture控件,改ID为IDC_PICTURE,然后 在函数中写入:

IStream *pStm; 
   long lDataSize = m_pRecordset->GetFields()->GetItem("读者相片")->ActualSize;
   if(lDataSize > 0)
   { 
   _variant_t varBLOB;  
   varBLOB = theApp.m_data.m_pRecordset->GetFields()->GetItem("读者相片")->GetChunk(lDataSize);   
   if(varBLOB.vt == (VT_ARRAY | VT_UI1))
   {
     char *pBuf = NULL;
     SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
     HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, lDataSize); 
     LPVOID pvData = NULL; 
     if (hGlobal != NULL) 
     { 
     if ((pvData = GlobalLock(hGlobal)) != NULL) 
     { 
       memcpy(pvData,pBuf,lDataSize);
       SafeArrayUnaccessData (varBLOB.parray);
       GlobalUnlock(hGlobal); 
       CreateStreamOnHGlobal(hGlobal, TRUE, &pStm); 
     } 
     else
       AfxMessageBox("加载图片失败!");
     } 
     else
     AfxMessageBox("申请内存失败!");
    
   }
   CWnd *pWnd = GetDlgItem(IDC_PICTURE); 
   CRect rect; 
   pWnd->GetClientRect(&rect); 
   CDC *pDC = pWnd->GetDC(); 
   IPicture *pPic; 
   if(SUCCEEDED(OleLoadPicture(pStm,lDataSize,TRUE,IID_IPicture,(LPVOID*)&pPic))) 
   { 
     OLE_XSIZE_HIMETRIC hmWidth;    
     OLE_YSIZE_HIMETRIC hmHeight; 
     pPic->get_Width(&hmWidth); 
     pPic->get_Height(&hmHeight);    
     if(FAILED(pPic->Render(*pDC,0,0,rect.Width(),rect.Height(),0,hmHeight,hmWidth,-hmHeight,NULL))) 
     AfxMessageBox("渲染图像失败!"); 
     pPic->Release(); 
   }
   }


这样写也会出现当窗口重绘窗口图片就会消失的问题,可以把上面的函数写在OnPaint()中.整个显示,存取和访问图片的程序就已经完成了.

  CoInitialize(NULL);
       _ConnectionPtr m_pConnect;
       try
       {
              // 创建Connection对象
              m_pConnect.CreateInstance("ADODB.Connection");
              // 设置连接字符串,必须是BSTR型或者_bstr_t类型
              _bstr_t strConnect = "Provider=SQLOLEDB.1;Password=111111;Persist Security Info=True;User ID=sa;Initial Catalog=Picture;Data Source=SHOWFLY\SQL2005";
              m_pConnect->Open(strConnect,"","",adModeUnknown);
       }
       // 捕捉异常
       catch(_com_error e)
       {
              // 显示错误信息
              AfxMessageBox(e.Description());
       }
       CFile   fileAdd;
       if(fileAdd.Open("F:/20087610203.JPG",CFile::modeRead)==0)    //打开文件
              return;
       _variant_t   varChunk;
       long   m_nFileLen   =   fileAdd.GetLength();
       BYTE*   m_pBMPBuffer;
       m_pBMPBuffer = new BYTE[m_nFileLen];
       if(m_pBMPBuffer==NULL)
              return;
       fileAdd.Read(m_pBMPBuffer,m_nFileLen);
//向数据库添加图片
       _RecordsetPtr m_pRecordset;
       m_pRecordset.CreateInstance(__uuidof(Recordset));
       try{
              m_pRecordset->Open(_variant_t("dbo.userphoto"),_variant_t((IDispatch*)m_pConnect,true),adOpenKeyset,adLockOptimistic,adCmdTable);
       }
       catch(_com_error &e)
       {
              ::MessageBox(NULL,"无法打开userphoto表!","提示",MB_OK|MB_ICONWARNING);
       }
       char        *pBuf = (char*)m_pBMPBuffer;
       VARIANT              varBLOB;
       SAFEARRAY  *psa;
       SAFEARRAYBOUND    rgsabound[1];
       m_pRecordset->AddNew();                                              ///添加新记录
       m_pRecordset->PutCollect("username",_variant_t("小李"));             ///为新记录填充username字段
       m_pRecordset->PutCollect("old",_variant_t((long)28));                 ///填充old字段
       if(pBuf)
       {
              rgsabound[0].lLbound = 0;
              rgsabound[0].cElements = m_nFileLen;
              psa = SafeArrayCreate(VT_UI1, 1, rgsabound);                      ///创建SAFEARRAY对象
              for (long i = 0; i < (long)m_nFileLen; i++)
                     SafeArrayPutElement (psa, &i, pBuf++);                         ///将pBuf指向的二进制数据保存到SAFEARRAY对象psa中
              varBLOB.vt = VT_ARRAY | VT_UI1;                                   ///将varBLOB的类型设置为BYTE类型的数组
              varBLOB.parray = psa;                                             ///为varBLOB变量赋值
              m_pRecordset->GetFields()->GetItem("photo")->AppendChunk(varBLOB);///加入BLOB类型的数据
       }
       m_pRecordset->Update();                                              ///保存我们的数据到库中


//从数据库读出图片
       long   lDataLength = m_pRecordset->GetFields()->GetItem(_variant_t("photo"))->ActualSize;
       if (lDataLength>0)
       {
              _variant_t   varBLOB;
              varBLOB=m_pRecordset->GetFields()->GetItem(_variant_t("photo"))->GetChunk(lDataLength);
              if(varBLOB.vt== (VT_ARRAY|VT_UI1) && varBLOB.vt!=VT_EMPTY && varBLOB.vt!=VT_NULL )
              {
                     BYTE *pBuf = NULL;
                     pBuf = (BYTE*)GlobalAlloc(GMEM_FIXED,lDataLength);
                     SafeArrayAccessData(varBLOB.parray,(void   **)&pBuf);
                     CFile   outFile("D:/20087610203.bmp",CFile::modeCreate|CFile::modeWrite); //构造新文件,如果文件存在,则长度变为0
                     outFile.Write(pBuf,lDataLength);
                     outFile.Close();
                     SafeArrayUnaccessData (varBLOB.parray);
              }
       }
       m_pRecordset->Close();
       m_pConnect->Close();
       ::CoUninitialize();

http://www.cnblogs.com/-clq/archive/2011/08/27/2155342.html

原文地址:https://www.cnblogs.com/wxl845235800/p/7430008.html