各位大虾:
   请问如何将一个文件(任意一个文件)存储到sql server 2000数据库中(是否可以存在一个字段当中),使用vc.
   应该用什么方法,字段应该设置成什么格式?希望能提供代码!
   谢谢!

解决方案 »

  1.   

    使用blob字段保存任意大小的二进制数据,不过代码访问这种字段稍微复杂一些。
      

  2.   

    4f正解,设定数据库时用IAMGE类型
      

  3.   

    ADO 方式
    try{

    //先用 CFileDialog 得到文件 FileName
    CFile myfile;
    CFileException e;
    //打开文件
    if( !myfile.Open(FileName, CFile::modeRead, &e ) )
    {
    return;
    }
    BYTE* pbuf;
    long len = myfile.GetLength();
    pbuf = new BYTE[len];
    if(pbuf == NULL)
    return;                             //allocate memory error;
    myfile.ReadHuge(pbuf,len);          //read the file into memory
    BYTE *pBufEx;
    pBufEx = pbuf;
    // 构造安全数组并放到一个varint变量中 SAFEARRAY* psa;
    SAFEARRAYBOUND rgsabound[1];
    rgsabound[0].lLbound = 0;
    rgsabound[0].cElements = len;
    psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
    for (long i = 0; i < len; i++)
    SafeArrayPutElement (psa, &i, pBufEx++);
    _variant_t varBLOB;
    varBLOB.vt = VT_ARRAY | VT_UI1;
    varBLOB.parray = psa;
    delete []pbuf;
    myfile.Close();
    if(len>0)
       rs->Fields->GetItem(/*IMAGE字段*/)->AppendChunk(varBLOB);
    }catch (...) {
    return;
    }
      

  4.   

    楼上的代码还是有些不明白的地方
    我是用sql语句,应该如何写呢?
    TO jameshooo :
    请说的详细一些,是否有具体的代码?
      

  5.   

    7楼给的就是代码。纯粹的SQL语句不能访问blob数据。
      

  6.   

    那应该怎么写进去啊?
    怎么读出来啊?SAFEARRAY* psa; 
    SAFEARRAYBOUND rgsabound[1]; 
    rgsabound[0].lLbound = 0; 
    rgsabound[0].cElements = len; 
    psa = SafeArrayCreate(VT_UI1, 1, rgsabound); 
    for (long i = 0; i  < len; i++) 
    SafeArrayPutElement (psa, &i, pBufEx++); 
    _variant_t varBLOB; 
    varBLOB.vt = VT_ARRAY  ¦ VT_UI1; 
    varBLOB.parray = psa; 
    delete []pbuf; 
    myfile.Close(); 
    if(len>0) 
       rs->Fields->GetItem(/*IMAGE字段*/)->AppendChunk(varBLOB); 
    这一段能不能给点注释啊?如何读出来呢?
      

  7.   

    AppendChunk是写数据,GetChunk是读数据。
    二进制数据读写必须使用SAFEARRAY,所以看起来代码有点复杂。
      

  8.   

    不是可不可以的问题,估计当作一个BLOB插入肯定没问题,但是这是数据库设计的大忌吧,好多数据库设计的建议都是不要这么做。这样做至少从我看来没有任何好处,坚持一个没有好处的算法不知道在干吗
      

  9.   

    按照自己的需要去选择技术去做。但是可以考虑1:存储文件路径到数据库中。2:可以把文件内容存储到数据库中。
    其中2,可以用image类型去存二进制流,方便你序列化和反序列化。或者直接存文件字符串进去。
      

  10.   

    在实现7楼的代码时,还有两个问题,希望能得到大家帮忙:
    1、在sql sever中建表时,数据类型选择 image 数据类型时,长度不能改变,只能为16,这是不是太小了啊?如果存储文件较大怎么办啊?
    2、
    rs->Fields->GetItem(/*IMAGE字段*/)->AppendChunk(varBLOB);
    这段话中,
    rs是这样  _RecordsetPtr  rs 定义的吗?
    再就是怎么确定是哪个表呢?连接数据库只能是连接数据库,不能确定是哪个表啊。假如我的表的名称是record,字段名称是filecontent,
    调用时写成record.filecontent可以吗?
      

  11.   


      BLOB 数据在 SQL Server 数据库中主要由 IMAGE 类型体现,最大容量为 2GB 。其存储方式不同于普通的数据类型,对于普通类型的数据系统直接在用户定义的字段上存储数据值,而对于 IMAGE 类型数据,系统开辟新的存储页面来存放这些数据,表中 IMAGE 类型数据字段存放的仅是一个 16 字节的指针,该指针指向存放该条记录的 IMAGE 数据的页面。
    rs是这样  _RecordsetPtr  rs 定义的吗

    再就是怎么确定是哪个表呢?void OnRecordsetAddnew()
    {
    _RecordsetPtr pRS; HREFTYPE  hr = NOERROR; _bstr_t   bstrQuery("SELECT * FROM [record] WHERE myID IS NULL"); //假设myID是主键 ,这里打开一个不包含记录的记录集 _variant_t  vtNULL; vtNULL.vt = VT_ERROR;
    vtNULL.scode = DISP_E_PARAMNOTFOUND;

    try
    {
    hr = pRS.CreateInstance(__uuidof(Recordset));
    if(SUCCEEDED(hr))
    {
    pRS->PutRefActiveConnection(m_pConnection);  //m_pConnection 是以打开的 _ConnectionPtr 变量

    hr = pRS->Open(_variant_t(bstrQuery),
    vtNULL,
    adOpenForwardOnly,   
    adLockOptimistic,
    adCmdText);
    if (SUCCEEDED(hr))
    {
    //方案1
    //字段名list
    COleSafeArray vaFieldList;
    vaFieldList.CreateOneDim(VT_VARIANT,2);  //假设有2个字段

    LONG larrayIndex[1];
    //ID字段名
    larrayIndex[0] = 0;
    vaFieldList.PutElement(larrayIndex,&(_variant_t("myID")));

    //filecontent字段名
    larrayIndex[0] = 1;
    vaFieldList.PutElement(larrayIndex,&(_variant_t("filecontent")));

    //字段的值list
    COleSafeArray vaValueList;
    vaValueList.CreateOneDim(VT_VARIANT,2);
    //ID值
    larrayIndex[0] = 0;
    vaValueList.PutElement(larrayIndex,&(_variant_t("001"));

    //filecontent字段值
    larrayIndex[0] = 1;
    vaValueList.PutElement(larrayIndex,&varBLOB));  //varBLOB 是 7楼 代码的 _variant_t varBLOB; 
    pRS->AddNew(vaFieldList,vaValueList);
    pRS->Close();
    //方案2
    // pRS->AddNew();
    // pRS->PutCollect("myID",_variant_t("001"));
    // pRS->Fields->GetItem("filecontent")->AppendChunk(varBLOB);//varBLOB 是 7楼 代码的 _variant_t varBLOB; 
    // pRS->Update();
    // pRS->Close();
    }
    }
    }
    catch(_com_error & e)
    {
    TRACE("Error : %081x. \n",e.Error());
    TRACE("ErrorMessage : %s. \n",e.ErrorMessage());
    TRACE("Source : %s. \n",(LPCTSTR)_bstr_t(e.Source()));
    TRACE("Description : %s. \n",(LPCTSTR)_bstr_t(e.Description())); }
    catch(...)
    {
    TRACE("\n *** Unhandled Exception *** \n");
    }
    }
      

  12.   

    如果楼主要求性能好的可以考虑使用OLEDB API
      

  13.   

    我还没有实验17楼大哥的代码是否可以,请问  tvman  大哥: 你的方案二可以用吗?再就是如何从数据库里读出来文件呢?
    但是在运行7楼大哥的代码时报错了,是Runtime Error. 请问是怎么回事
      

  14.   

     //pRS->Fields->GetItem("filecontent")->AppendChunk(varBLOB);
     也可以改成
     pRS->PutCollect("filecontent",varBLOB); // pRS->Update() 后释放空间 SAFEARRAY
     ::SafeArrayDestroyData(psa);//从数据库获取数据
    _variant_t data = pRS->GetCollect("filecontent");

    if(::GetFileAttributes(name)!=-1)   //name 是你的文件名
        ::SetFileAttributes(name,FILE_ATTRIBUTE_NORMAL);//保存到文件
    CFile file;
    if(file.Open(name,CFile::modeCreate|CFile::modeWrite))
    {
      file.WriteHuge(data.parray->pvData,data.parray->rgsabound[0].cElements);
      file.Close();
    }