我用IdTCPClient传输文件后,文件在大小是一模一样的,但是传过的文件就是无法执行,用fc比较了一下有很多地方不一样。但传的文本文件却打开正常,但用fc比较还是不行,代码如下:客户端:
procedure TForm1.Button2Click(Sender: TObject);
var
  answer:string;
  MS:TMemoryStream;
  block:int64;
  i:integer;
  buff:PByteArray ;
  lastblock:integer;
  blocksize:int64;
  fs:TFileStream;
begin
  blocksize:=8000;
  tc.Host:='192.168.0.16';
  tc.Port:=1217;
  tc.Connect;
  tc.WriteLn('UPFILE');
  Answer:=tc.ReadLn;
  if Answer='YES' then
  begin
    fs:=TFileStream.Create(e1.Text,fmOpenRead);    if fs.Size>blocksize then
    begin
      block:=trunc(fs.Size/blocksize);
      lastblock:=fs.Size-block*blocksize;
    end
    else begin
      block:=0;
      blocksize:=fs.Size;
    end;
    tc.WriteInteger(blocksize);
    tc.WriteInteger(lastblock);
    tc.writeinteger(block);
    for i:=0 to block-1 do
    begin
      tc.WriteLn('NEXT');
      tc.WriteStream(fs,true,false,blocksize);
    end;//for;
    if block<>0 then
    begin
    tc.WriteLn('LAST');
    tc.WriteStream(fs,true,false,lastblock);
    end;
    tc.WriteLn('FINISH');    tc.Disconnect;
    fs.Free;
  end
end;
服务器端
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var
  msg:string;
  fs:tfilestream;
  buff:PByteArray ;
  blocksize:int64;
  lastblocksize:int64;
  blockcount:int64;
  i:integer;
begin
  msg:=Athread.Connection.ReadLn;
  if MSG='UPFILE' then
  begin
    athread.Connection.WriteLn('YES');    blocksize:=ATHREAD.Connection.ReadInteger;    lastblocksize:=athread.Connection.ReadInteger;    blockcount:=athread.Connection.ReadInteger();
    fs:=tfilestream.Create('d:\wpf.mp3',fmCreate);
    for i:=0 to blockcount-1 do
    begin
      Msg:=athread.Connection.ReadLn;
      if msg='NEXT' then
        athread.Connection.ReadStream(fs,blocksize);
      msg:='';
    end;//for    if blockcount<>0 then
    begin
    msg:=athread.Connection.ReadLn;
    if msg='LAST' then
      athread.Connection.ReadStream(fs,lastblocksize);
    end;
    msg:=athread.Connection.ReadLn;
    if msg='FINISH' then athread.Connection.Disconnect;
    fs.Free;
  end;
end;我感觉可能是同步有问题,但从代码上我又发现不到同步问题,还望大家帮忙。

解决方案 »

  1.   

    不用这么麻烦的吧?IdTCPServer/IdTCPClient有自动流控,不需要自己分块.client:
      tc.WriteLn('UPFILE');
      Answer:=tc.ReadLn;
      if Answer='YES' then
      begin
        fs:=TFileStream.Create(e1.Text,fmOpenRead);
        tc.WriteInteger( fs.Size );
        tc.WriteStream( fs, fs.Size );
        fs.Free;
      end;
      tc.Disconnect;server:
      msg:=Athread.Connection.ReadLn;
      if MSG='UPFILE' then
      begin
        athread.Connection.WriteLn('YES');    size:=ATHREAD.Connection.ReadInteger;
        fs:=tfilestream.Create('d:\wpf.mp3',fmCreate);
        athread.Connection.ReadStream(fs,size);
        fs.Free;
        AThread.Connection.Disconnect;
      end;
      

  2.   

    是你用了分块产生的错误。
    Client的发送块顺序:1、2、3、4、5
    Server的接收块顺序(可能):1、2、4、5、3
    那么你的文件在拼接时肯定是不对的(你在服务器代码里用了For,这是没有顺序的)
    你可以为你的块建个Record的数据结构,其中添上块的顺序信息,然后发送;服务器端根据块顺序拼接。
      

  3.   

    想要在传文件时显示进度,可以使用ONWork过程控制,首先传送文件大小,再利用FTPServer/FTPClient自动流控制,在ONWork过程中读取当前流的大小,累计之后除以文件大小得到百分比就可以了.并不需要自行分块,在自行分块时会出现N多问题,稍有不慎就会将文件写坏.