本人写的三层系统中,要要用TClentDataSet向数据库(DB2)中插入Blob字段类型的数据,该数据是一个word的文件(write.doc),虽然插了进去(当然Blob字段也进去了),但是读出来的文件却比原文件小,却打不开读出的文件,提示文件无效,请高手指点,写的方法如下:
procedure TForm1.Button3Click(Sender: TObject);
var
  stmFiles:Tfilestream;
  strFileName:String;
begin
 strFileName:='c:\write.doc';
 stmFiles:=Tfilestream.Create(strFileName,fmOpenRead);
try
clientdataset1.CommandText:='insert into userid.xt_blob(YHDM,YHMC,YHKL,QM)'+' values(''vts'',''笑眯眯'',''111'',:BB1)';//QM是一个BLOB字段类型.
  clientdataset1.Params.CreateParam(ftblob,'BB1',ptInput);
 clientdataset1.Params.ParamByName('BB1').LoadFromStream(stmFiles,ftblob);
  clientdataset1.Execute;
  clientdataset1.Params.Clear;
finally
  stmfiles.Free;
end;
end;
注意:
  1.数据库的字段大小大于该文件的大小好几倍,所以不存在字段容量不够大的问题
    2. 提交的是一个SQL的方法来插入,而不是要用什么Append,Post之类的方法来实现.
    3. 本人测试过,用TQuery插入的方法插入后,又用TQuery将其文件读出,一切都正常.但是我用TQuery插入的word文档,用TClientDataSet读出是正常的,所以证明我读出的代码没有任何问题.而用TClientDataSet插入的记录,再用TClientDataSet或TQuery读出后的文件却比原文件小了点,所以文件读出的是坏的,说明用TClientDataSet写入时的文件就不正确了.
    4.本人用的TSocketConnection连接,应用服务器端的BDE的BlobSize也设置的正确.所以该问题也排除.
    5.但是如果插入的文件是一个txt文件类型时,一切都正确.
    6.该问题也等到了一些网友的解答,但是经本人测试,好像也没有作用,也许是本人愚笨,写的不正确,所以烦请各为高手能给出一个完整的,经过测试过的方法,多谢大家的支持,问题一但解决,本人就散分!
本程序的读出代码如下(是正确的):
procedure TForm1.Button2Click(Sender: TObject);
var
  stmFiles:Tfilestream;
  strFileName:String;
begin
  strFileName:='c:\read.doc';
  if FileExists(strFileName) then
    deletefile(strFileName);
  stmFiles:=Tfilestream.Create(strFileName,fmCreate);
try
  clientdataset1.CommandText:='select * from userid.xt_blob where yhdm=''vts''';  clientdataset1.Open;
  clientdataset1.Last;
  clientdataset1.First;
  if clientdataset1.RecordCount >0 then
  begin
    TBlobField(clientdataset1.FieldByName('QM')).SaveToStream(stmFiles);
  end;
finally
   stmfiles.Free;
end;网友回答例子:
好像用DataSet的参数将BLOB字段的值传递给SQL只对BDE有效,对ClientDataSet或ADO是有问题的。
    所以,ClientDataSet或ADODataSet一般都是通过建立其BLOB字段的流对象来实现流操作。TClientDataSet可建立TClientBlobStream类型的流,TADODataSet可建立TADOBlobStream类型的流。
    在DELPHI的后期版本中还专门为TDataSet设计了一个虚函数CreateBlobStream,让不同类型的DataSet自己实现具体流。
    你改成这样试试:
    ......
    ClientDataSet1.CommandText := 'select * from atable';
    ClientDataSet1.Open;
    ClientDataSet1.Append;
    aStream := ClientDataSet1.CreateBlobStream('aBlobFieldName', bmReadWrite);
    aStream.CopyFrom(aFileStream, 0);
    ......    这些代码只是示范,有错当查!李战.深圳
文件大小相同吗?
我用tdataset.fieldby('bb1').asblob.loadfromstream(fp)存,没使用过这种方法存。
你读文件的代码拿出来看看
cds.Edit;
TBlobField(Cds.FindField('blob')).LoadFrom(MyMemoryStream);
cds.Post;
cds.ApplyUpdate;

解决方案 »

  1.   

    应该不能直接使用SQL的INSERT语句
      

  2.   

    应该有很多人讨论过这个问题,不过可能不好找,我把我的代码贴出来,那些代码肯定是可以运行的。服务器:Oracle+ADO+win2k
    function TDMF1Client.LoadFormat(F1book: TF1book): boolean;
    begin
      result := true;
      with cdsFormat do
      begin
        Active := false;
        CommandText := 'select * from XT_FB_YSB where rtrim(FORMATCODE)=''' + FormatInfo.FormatCode + '''';
        try
          active := true;
        except
          result := false;
          showmessage('从数据库读取格式失败。');
        end;
    end;
    end;procedure TfrmInterface.WriteFormatToCds(F1book: TF1book);
    var
        sTempFile: string;
    begin
        sTempFile := getSysTempPath + '\' + nTempFileName;
        f1book.Write(sTempFile, F1FileFormulaOne6);
        with DMF1Client do begin
            cdsFormat.first;
            if not cdsFormat.eof then
            begin
                cdsFormat.edit;
                cdsFormat.FieldByName('FORMATNAME').AsString := FormatInfo.FormatName;
                cdsFormat.FieldByName('FORMATKEY').AsString := FormatInfo.FormatKey;
                cdsFormat.FieldByName('FORMATTYPE').AsString := FormatInfo.FormatType;
                cdsFormat.FieldByName('CALLERFRAME').AsString := FormatInfo.CallerFrame;
            end
            else
            begin
                cdsFormat.insert;
            end;
            cdsFormat.FieldByName('FORMATCODE').AsString := FormatInfo.FormatCode;
            cdsFormat.FieldByName('FORMATNAME').AsString := FormatInfo.FormatName;        cdsFormat.FieldByName('FORMATKEY').AsString := FormatInfo.FormatKey_inFormatTable;
            cdsFormat.FieldByName('FORMATTYPE').AsString := FormatInfo.FormatType;
            cdsFormat.FieldByName('CALLERFRAME').AsString := FormatInfo.CallerFrame;
            cdsFormat.FieldByName('DATAAREA').AsString := FormatInfo.DataArea;
            cdsFormat.FieldByName('CHARAREA').AsString := FormatInfo.CharArea;
            cdsFormat.FieldByName('MEMOAREA').AsString := FormatInfo.MemoArea;
            try            cdsFormatFORMATCONTENT.LoadFromFile(sTempFile);//和数据库中BLOB字段对应的Field对象,
                                                               //定义为  cdsFormatFORMATCONTENT: TBlobField;
                                                               //在字段管理器里生成            cdsFormat.post;
                deleteFile(pchar(sTempFile));
            except
                ShowMessage('保存格式出错');
            end;
        end;
    end;function TDMF1Client.SaveFormat(F1book: TF1book): boolean;
    var
      sTempFile: string;
      i: Integer;
    begin
      result := true;
     with cdsFormat do begin
     try i := cdsFormat.ApplyUpdates(0);
          result := (i = 0);
        except
          ShowMessage('保存格式出错');
          result := false;
        end;
      end;
      scF1Format.Connected := false;end;
      

  3.   

    如果直接用sql语句语句的话,好象有这个问题,但用数据集操作的话是可以的
      

  4.   

    我2000年用D5+BDE+DB2的时候也出现过这种问题,存进去的图片取出来总是小那么一点。
    当时我上Borland看了,是个D5的Bug,没有办法,只能自己解决。
    我是自己在appserver上加了个uploadpic的接口,然后将图片转换为olevariant类型来传送到Appserver,然后Appserver再从olevariant转换到Tmemorystream,在Appserver中插入数据库中。然后搞定。
    原来的代码得找一找,不知道还在不在。
    楼主用的是D5吗?
      

  5.   

    我用的是D6,保存图片没有问题。
    客户端 + socket + 中间层 + ado + sql server;
    读出、写入借助stream。
    写入:
    var 
    ms:tmemorystream;
    begin
      ms:=TmemoryStream.Create;
      ms.Loadfromfile(“1.jpg”);
     if ms.size>0 then
     begin
       ms.position:=0;
       (Clientdateste1.fieldbyname('dipicture') as Tblobfield).loadfromstream(ms);
     end ;
    end;读出:
     var 
      ms:tstream;
      myjpg:tjpegImage;
    begin
      ms:=clientdataset1.createblobstream(clientdataset1.fieldbyname('dipicture'),bmread);
    if ms.size>0 then
    begin
      ms.position:=0;
      myJpg:=tjpegimage.create;
      myJpg.loadFromstream(ms);
      Image1.Picture.assign(myjpg);//在Image1中显示出来
    end;
    end;
    上面的代码绝对没错我测试过的。
    我没有时间写更多了,希望这些有所帮助。
      

  6.   

    写入doc文件和图片是类似的,希望上面的对你有帮助。我要下班了,只能说这些了。