Click here to Skip to main content
Email Password   helpLost your password?
  • Download demo project - 29 Kb
  • Sample Image - UsingBlob.gif

    At times, storing images and other types of documents like word document, or excel spread sheet or even a compressed zip file in the database is inevitable. MFC provides a supporting class to handle these BLOBs called CLongBinary. It is just a wrapper around the HGLOBAL of WIN32. But how do you use it? The wizard creates a member variable of type CLongBinary in your record set object and also creates the corresponding RFX routine (RFX_LongBinary).

    Okay, does it mean that you can use this member just like any other variable? No, That's where this document comes in handy. For regular data types, all you have to is create an instance of the recordset object, assign the values and call Update. But for BLOBs, you have to do something special. For inserting BLOBs, you have to remember 3 points.

    1. Allocate and lock the storage buffer using GlobalAlloc() and GlobalLock() calls
    2. Prepare the recordset for blob operation using SetFieldDirty() and SetFieldNull() calls
    3. Unlock the storage buffer

    By default, the destructor of the CLongBinary will delete the buffer using GlobalFree() call. So you don't have to bother about freeing the memory. Reading from the database is pretty simple. All you have to do is lock the buffer.

    Following code snippet shows how to do this in the actual code:

    // Store the Image to database table
    
    // 
    
    try
    {
        dbImages.Open();
        dbImages.AddNew();
    
        CFile	fileImage;
        CFileStatus	fileStatus;
    
        fileImage.Open("c:\\winnt\\winnt256.bmp", CFile::modeRead);
        fileImage.GetStatus(fileStatus);
    
        dbImages.m_BLOBName = fileImage.GetFileTitle();
        dbImages.m_BLOBImage.m_dwDataLength = fileStatus.m_size;
    
        HGLOBAL hGlobal		= GlobalAlloc(GPTR,fileStatus.m_size);
        dbImages.m_BLOBImage.m_hData = GlobalLock(hGlobal);
    
        fileImage.ReadHuge(dbImages.m_BLOBImage.m_hData,fileStatus.m_size);
    
        dbImages.SetFieldDirty(&dbImages.m_BLOBImage);
        dbImages.SetFieldNull(&dbImages.m_BLOBImage,FALSE);
        dbImages.Update();
    
        GlobalUnlock(hGlobal);
    
        dbImages.Close();
    
        pList->InsertItem(0,fileImage.GetFileTitle());
    }
    catch(CException* pE)
    {
        pE->ReportError();
        pE->Delete();
        return;
    }

     

    // To restore image from db table
    
    CdbImages   dbImages(&theApp.m_DB);
    CString     strFileName = pList->GetItemText(nIndex,0);
    dbImages.m_strFilter.Format("BLOBName = '%s'",strFileName);
    try
    {
        dbImages.Open();
        if  (dbImages.IsEOF())
            AfxMessageBox("Unable to get image from db");
        else
        {
            char    tmpPath[_MAX_PATH+1];
            GetTempPath(_MAX_PATH,tmpPath);
    
            strFileName.Insert(0,tmpPath);
            
            CFile	outFile(strFileName,CFile::modeCreate|CFile::modeWrite);
            LPSTR	buffer = (LPSTR)GlobalLock(dbImages.m_BLOBImage.m_hData);
            outFile.WriteHuge(buffer,dbImages.m_BLOBImage.m_dwDataLength);
            GlobalUnlock(dbImages.m_BLOBImage.m_hData);
            outFile.Close();
    
            theApp.OpenDocumentFile(strFileName);
        }
    
        dbImages.Close();
    
    }
    catch(CException* pE)
    {
        pE->ReportError();
        pE->Delete();
        return;
    }
    
    

    The demo project uses an Access database to store the images. This project also demonstrates the following:

    The images are displayed using the simplest technique of using BitBlt() call. It does not use any Palettes because it is beyond the scope of this article.

    You must Sign In to use this message board.
     
     
    Per page   
     FirstPrevNext
    Generalerror C2039: 'WriteHuge' : is not a member of 'CFile' g:\mainfrm.cpp and Error and error C2039: 'ReadHuge' : is not a member of 'CFile' g:\mainfrm.cpp 205
    KYAW KYAW OO
    18:49 31 Jul '08  
    Dear Narayanan,


    First of all, I would like to say, thank you for your contribution in here.

    I am a begineer of image processing and database. I found out the above error and tried to solve it myself but still there.

    I will be looking forward to hearing from your advice.



    Thanks and best regards
    Ko Ko
    GeneralRe: error C2039: 'WriteHuge' : is not a member of 'CFile' g:\mainfrm.cpp and Error and error C2039: 'ReadHuge' : is not a member of 'CFile' g:\mainfrm.cpp 205
    Rolando E. Cruz-Marshall
    3:04 26 Sep '08  
    D'Oh! If you'd search for "WriteHuge" with your MS Visual Studio Documentation you will notice it states that method is now obsolete. At the time this article was written WriteHuge was available at the time.

    Code still works...

    Rolando Suspicious

    GeneralReally Good
    manish rastogi
    0:48 3 Jul '08  
    It is really good.
    Thanks Shekar Narayanan. Smile
    Generalsome question about insert images,please tell me!
    freesky323
    4:03 25 Jan '07  
    how to insert images into oracle using BLOB?
    Questionnew record
    ali21212121212121
    5:36 9 May '06  
    How to add a record for descriping the picture?Confused
    Generalhow to insert image to SQL server
    thanhthuyvn_vtajkhskjakjd
    21:18 12 Nov '05  
    how to insert image to SQL server?
    thanks for your help.

    An Phung Nguyen
    GeneralBLOB
    pmk_8
    2:04 20 Jun '05  
    how to insert images into oracle using BLOB?
    GeneralAn annotation
    buho_usp
    5:17 7 Jun '05  
    Hi,

    I was finding some information about add this kind of object to parameters using ado(msado15.dll), but i didnt get something useful, just some about appendChunk and getchunk but nothing related to add blobs to some parameter or what type it would be...adArray maybe??...
    something like this:

    pParam1 = pCommand->CreateParameter( "@Image", adArray???, adParamInput,sizeoff(????),????);

    I ll be thankfull for some comments and advices...D'Oh!


    GeneralODBC Crash with CLongBinary
    Anonymous
    23:53 21 Oct '04  

    In Sybase, Field "Property" is a Image and it's size almost 16k
    CRecordset DoFieldExchange like:
    ...
    RFX_LongBinary(pFX, _T("[Property]"), m_Property);
    ...

    I use it like:
    try
    {
    int ret = dbset.Open(CRecordset::snapshot,strSql);
    if(dbset.IsBOF())
    return false;
    while(!dbset.IsEOF())
    {
    ... //read data
    if(!dbset.CanScroll())
    break;
    dbset.MoveNext();
    }
    }

    After thousands of call, the program will crash at Open or MoveNext, thus see memory of the m_Property, m_Property.data is NULL and m_Property.m_dwDataLength is a very large num.

    Check the assemble code from the source code, it corrupt in file dbrfx.cpp statement

    case CFieldExchange::Fixup:
    // Get the size of the long binary field
    *plLength = pFX->GetLongBinarySize(nField);

    Seems like when get the image data from the database, it's data was damage.


    I know this is another Program is writing the db in the same time and will modify the record, is it the reason cause the crash, and would someone tell me the really reason?
    thanks

    Please Help me! Emergency!
    Emil : xiazgli@163.com
    xzg
    GeneralODBC Crash with CLongBinary
    Anonymous
    23:34 21 Oct '04  
    In Sybase, Field "Property" is a Image and it's size almost 16k
    CRecordset DoFieldExchange like:
    ...
    RFX_LongBinary(pFX, _T("[Property]"), m_Property);
    ...

    I use it like:
    try
    {
    int ret = dbset.Open(CRecordset::snapshot,strSql);
    if(dbset.IsBOF())
    return false;
    while(!dbset.IsEOF())
    {
    ... //read data
    if(!dbset.CanScroll())
    break;
    dbset.MoveNext();
    }
    }

    After thousands of call, the program will crash at Open or MoveNext, thus see memory of the m_Property, m_Property.data is NULL and m_Property.m_dwDataLength is a very large num.

    I know this is another Program is writing the db in the same time and will modify the record, is it the reason cause the crash, and would someone tell me the really reason?
    thanks

    xzg



    Generaldo the method work when considering oracle
    xuyang_deng
    22:28 21 Apr '04  
    dose the method work well when using it for a oracle database,
    can you give me the same example when i connet a oracle database
    thank you

    inga_2000
    GeneralCByteArray
    mjwilliamson
    2:16 16 Mar '04  
    Hi

    Does anyone know how to store and retireve data using the CByteArray
    class?

    Thanks

    Mark
    GeneralExcel files
    Al Findlay
    8:12 17 Feb '04  
    Hello!

    I have modified the code slightly so I can get this working for small .rtf files but not having much joy with Excel files (approx 20k big). I am running VC++ .NET 1.0 Framework.

    The problem occurs on reading the file contents and writing them to a file. The small .rtf file would be created perfectly. However, with the Excel files, lpszbuffer in the below line comes out as a small garbled string and so falls over on CFile::Write...

    lpszBuffer = (LPSTR) ::GlobalLock( lbData.m_hData );

    Can anybody help?

    Thanks,

    Al

    Alistair Findlay
    Software Developer
    http://www.thehob.co.uk
    GeneralError: Data truncated
    mef526
    7:06 3 Jul '03  
    I am have trouble getting the code to work when there is a record in the table. I get the error data truncated. Some research has shown that there is a KB article PSS ID Number: 141303 in MSDN at
    ms-help://MS.VSCC.2003/MS.MSDNQTR.2003APR.1033/enu_kbvisualc/visualc/141303.htm

    http://support.microsoft.com/?kbid=141303

    that describes the situation: a bug in MFC. However the solution does not work. It looks like the interface to CDatabase and CRecordset has changed since the workaround was created.

    Does anyone have any idea what is going on wiht the issue?

    Thanks...

    GeneralRe: Error: Data truncated
    wancol
    22:59 25 Aug '03  
    the Bug is not exist after Visual c++ 4.2 ,
    before you open you RecordSet ,if your Oracle Table has BLOB column ,you must
    set the Member m_bLongBinary=TRUE; then it will not throw the exception .




    later upload
    Generalproblem when call update()
    CS429
    22:24 1 Jul '03  
    hello thanks for your code ,but i need help
    i use SQL server 2000 if my data is english language when i call update() it's ok but if my data is any language such as thai language when i call update() it change to ?????? who can resolve this problem Confused

    ::: if i call addnew() without image data it's ok
    GeneralCan u give an example with ADO about how to save a CLongBinary into database?
    ztliu01
    23:22 4 Jun '03  
    thanx!
    GeneralStore Images with RecordsetPtr
    jsundjsund
    22:57 7 Apr '03  
    I using c++ to make CGI and want to create and store images from and to a database.

    My code to do other communication yuo can see below, to retrieve a textfield is ok but I can not find out how to create a image see "???"


    CString path="E:\\program files\\Cplusplus\\test\\";
    CString searchstr="SELECT * FROM T_Attachments WHERE C_PrimaryKey='" + sKey + "'";
    CoInitialize(NULL);

    _RecordsetPtr pRs = NULL; //-- This is the Recordset Variable
    _ConnectionPtr pCn = NULL; //-- This is the Connection Variable

    _bstr_t strCnn("DSN=SupportDSN; UID=xx; PWD=xx");

    pCn.CreateInstance(__uuidof(Connection));
    pCn->Open(strCnn,"xx","xx",adConnectUnspecified);

    pRs.CreateInstance(__uuidof(Recordset));
    pRs->Open((LPCTSTR)searchstr,
    _variant_t((IDispatch *)pCn,true), adOpenKeyset,
    adLockOptimistic, adCmdText);

    path+=(char*) ((_bstr_t) pRs->GetFields()->GetItem("C_Name")->GetValue());

    CFile outFile(path,CFile::modeCreate|CFile::modeWrite);
    buffer = ???
    outFile.WriteHuge(buffer,sizeof(buffer));
    outFile.Close();
    GeneralOut of memory error with Sybase
    Stan Harris
    17:10 20 Feb '03  
    I am trying to allow the insert/retrieval of BLOBS to my ASA database. When there are no records in the database I am able to add one record. When I try to open the table with any data in the table I get an MFC out of memory error. Has anyone seen this, or have any insight to the problem.

    Thanks

    Stan
    GeneralRe: Out of memory error with Sybase
    Wes Jones
    9:06 28 Jul '06  
    This may be 3 years late or so, but maybe it'll help someone:

    I use Sybase ASA & I've seen this too... I think it has to do w/ the ODBC API call that tells MFC the size of the field after the SELECT statement is executed & before the SQLFetch()/SQLGetData call is made. I think it's SQLDescribeCol... for LONG VARCHAR & LONG BINARY fields, Sybase reports a really huge number, something like what -1 looks like when you view it as an unsigned long. That's not exactly the #, but that's why it gives the 'Out of Memory' exception when it tries to allocate enough memory for the column.

    My fix for my LONG VARCHAR fields was to use a CString instead of a CLongBinary, then in CMyRecordset::DoFieldExchange, change the RFX_Text call like so:

    RFX_Text(pFX, _T("[myBlob]"), m_strBlob, 4096 * 4, SQL_LONGVARCHAR);

    It's not the best to pass a hard coded max buffer size, but it worked for me.
    I think you can change that to a variable or function result, but it probably only works if you aren't doing bulk fetching w/ your recordset.
    Still working on what to do w/ LONG BINARY tho....
    GeneralHow to Delete or Modify a BLOB?
    Mate
    16:48 7 Jan '03  
    ok for the creation (addnew) of a BLOB. It work perfectly and my database is just growing up as long as I test it. So how to delete a record. The classical Delete() function gives back error message (I do not previously set the Addnew() or Edit() function as it is requested for the Delete mode). The Update() function gives back the same error (with the Recordset previously set to Edit() mode ).

    Thank you very much

    Mate
    GeneralRe: How to Delete or Modify a BLOB?
    Ben Mathews
    11:42 13 Feb '03  
    You need to give a lot more detail to get help from anyone. There are a lot of error messages that you have left us to guess about.
    GeneralRe: How to Delete or Modify a BLOB?
    ipadilla
    7:31 4 Sep '05  
    ok for the creation (addnew) of a BLOB. It work perfectly and my database is just growing up as long as I test it. So how to delete a record. The classical Delete() function gives back error message (I do not previously set the Addnew() or Edit() function as it is requested for the Delete mode). The Update() function gives back the same error (with the Recordset previously set to Edit() mode ).

    GeneralProblem while updating the BLOB to ORACLE using CLongBinary
    Mytreya
    4:14 25 Mar '02  
    I've been using OCI library calls till recently to talk
    to ORACLE D/B and it works pretty fine. But when i try
    to use ODBC for the same, i am not sure as how the
    BLOB object needs to be updated to the D/B. I've tried
    it as mentioned in this article, but encounter the error
    MissingExpression: ora-00936.
    Also when we use OCI calls, we select the OCILobLocator for
    update, write into it and just commit. But in the ODBC
    version, when i used the edit/update, i observed that
    the ultimate SQL statement that is being framed is an
    "update".
    If anyone has done the BLOB updation to ORACLE using
    ODBC, please do let me know as how it needs to be done.

    GeneralRe: Problem while updating the BLOB to ORACLE using CLongBinary
    DiWa
    6:18 7 Aug '02  
    It strongly depends on the ODBC-Driver Version you're using. i.e. using the latest driver 8.1.77 to read/write a long raw into a 8.1.7 Oracle database with this sample will work, also if you are using the Merant (ex-Intersolv) drivers.
    Using older Oracle drivers often leads into the problems you encountered.


    Last Updated 1 Dec 1999 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010