Indy 10 文件传输

客户端

procedure TfrmClient.btnSaveClick(Sender: TObject);
var
    cmd:String; //服务器通信命令
    ASize,TotalSize:Int64;//缓冲区大小,文件流大小
    AFileStream:TFileStream;//文件流变量
begin
    IdTCPClient1.Host:=Edit1.Text;
    IdTCPClient1.Port:=StrToIntDef(Edit2.Text,9225);
    IdTCPClient1.Connect;
    Try
      IdTCPClient1.IOHandler.WriteLn('BEGIN');//提示客户端开始接收
      cmd:=IdTCPClient1.IoHandler.ReadLn;
      //以'|'分离文件名
      dlgSave.FileName:=Copy(cmd,Pos('|',cmd)+1,Length(cmd));
      if not dlgSave.Execute then
      begin
          IdTCPClient1.IOHandler.WriteLn('CANCEL');//告诉服务器取消
          IdTCPClient1.Disconnect;
          Exit;
      end;
      //分离文件大小
      TotalSize:=StrToInt(Copy(cmd,0,Pos('|',cmd)-1));
      //建立文件流准备接收
      AFileStream:=TFileStream.Create(dlgSave.FileName,fmCreate);
      try //开始循环接受
          Repeat
              IdTCPClient1.IOHandler.Writeln(IntToStr(AFileStream.Size));//发送当前传输的位置
              ASize:=Min(TotalSize-AFileStream.Size,IdTCPClient1.IOHandler.RecvBufferSize);
              //选择剩余大小和缓冲区大小小的一个作为传输的大小
              IdTCPClient1.IOHandler.ReadStream(AFileStream,ASize);//接收流
              StatusBar1.Panels[1].Text:=Format('当前传输位置%d/大小%d',[AFileStream.Size,TotalSize]);
              Application.ProcessMessages;
          Until AFileStream.Size=TotalSize;  //当大小一致时退出循环
      finally
          AFileStream.Free;//释放文件流
      end;
      IdTCPClient1.IOHandler.WriteLn('END');//告诉服务器已经接收完毕
      StatusBar1.Panels[1].Text:='传输文件成功';
    except
          StatusBar1.Panels[1].Text:= '连接服务器失败或者对方已经中断传输!';
    End;
    IdTCPClient1.Disconnect;              //断开连接
 end;

服务端

unit PasServer;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdContext, IdBaseComponent, IdComponent, IdCustomTCPServer,
  IdTCPServer, StdCtrls, ComCtrls,Math;

type
  TfrmServer = class(TForm)
    Label1: TLabel;
    Edit1: TEdit;
    btnStart: TButton;
    btnExit: TButton;
    btnOpen: TButton;
    IdTCPServer1: TIdTCPServer;
    OpenDialog1: TOpenDialog;
    Label2: TLabel;
    Edit2: TEdit;
    Label3: TLabel;
    Edit3: TEdit;
    StatusBar1: TStatusBar;
    ProgressBar1: TProgressBar;
    btnCancel: TButton;
    procedure btnOpenClick(Sender: TObject);
    procedure btnExitClick(Sender: TObject);
    procedure btnStartClick(Sender: TObject);
    procedure IdTCPServer1Connect(AContext: TIdContext);
    procedure IdTCPServer1Execute(AContext: TIdContext);
    procedure FormCreate(Sender: TObject);
    procedure btnCancelClick(Sender: TObject);
  private
    { Private declarations }
    AFileStream:TFileStream;
    procedure ButtonBegin;
    procedure ButtonEnd;
  public
    { Public declarations }
  end;

var
  frmServer: TfrmServer;

implementation

{$R *.dfm}

procedure TfrmServer.ButtonBegin;
begin //VCL开始状态设置
    btnStart.Enabled:=False;
    btnExit.Enabled:=False;
    btnCancel.Enabled:=True;
    btnOpen.Enabled:=False;
end;
procedure TfrmServer.ButtonEnd;
begin //VCL结束状态设置
    btnStart.Enabled:=True;
    btnExit.Enabled:=True;
    btnCancel.Enabled:=False;
    btnOpen.Enabled:=True;
end;
procedure TfrmServer.btnStartClick(Sender: TObject);
begin
    if not FileExists(Edit1.Text) then  //检测文件是否存在
    begin
        ShowMessage('文件不存在,请重新选择!!!');
        exit;
    end;
    //建立文件流
    AFileStream:=TFileStream.Create(Edit1.Text,fmOpenRead);
    ProgressBar1.Max:=AFileStream.Size;
    ProgressBar1.Position:=0;
    ButtonBegin;//VCL开始状态设置
    //服务器准备好连接
    IdTCPServer1.DefaultPort:=StrToIntDef(Edit2.Text,9225);
    if not IdTCPServer1.Active then IdTCPServer1.Active:=True;
end;

procedure TfrmServer.btnCancelClick(Sender: TObject);
begin
    StatusBar1.Panels[1].Text:='传输取消.....';
    AFileStream.Free;  //释放文件流
    ButtonEnd;   //VCL结束状态设置
end;

procedure TfrmServer.btnExitClick(Sender: TObject);
begin
    if IdTCPServer1.Active then
        IdTCPServer1.Active:=False;
    Close;
end;

procedure TfrmServer.btnOpenClick(Sender: TObject);
begin
    OpenDialog1.Execute;
    if OpenDialog1.FileName<>'' then
    begin
        Edit1.Text:=OpenDialog1.FileName;
        btnStart.Enabled:=True;
    end;
end;

procedure TfrmServer.FormCreate(Sender: TObject);
begin
    StatusBar1.Panels[1].Text:='文件传输服务器V1.1';
    btnStart.Enabled:=False;
    btnCancel.Enabled:=False;
end;

procedure TfrmServer.IdTCPServer1Connect(AContext: TIdContext);
begin
      Edit3.Text:=AContext.Binding.IP;
end;

procedure TfrmServer.IdTCPServer1Execute(AContext: TIdContext);
var
    cmd:string;       //客户端命令信息
    ASize:Integer;    //需要的传输流大小
begin
    with AContext.Connection do  //已经连街上的一个进程
    begin
        cmd:=UpperCase(IoHandler.ReadLn); //客户端发送的命令字符串
        if cmd='BEGIN' then //开始传输....
        begin
            //告诉客户机文件大小及文件名
            IoHandler.WriteLn(Format('%d|%s',[AFileStream.Size,ExtractFileName(Edit1.Text)]));
            StatusBar1.Panels[1].Text:='准备传输......';
            exit;
        end;
        if cmd='CANCEL' then //中止传输
        begin
            StatusBar1.Panels[1].Text:='客户中止传输....';
            //保持传输状态
            Exit;
        end;
        if cmd='END' then
        begin
            //文件传输完毕
            btnCancel.Click;
            StatusBar1.Panels[1].Text:='文件传输已经完成...';
            Exit;
        end;
        //按照指定位置传输文件
        AFileStream.Seek(StrToInt(cmd),soFromBeginning);//转到文件的传输位置
        ASize:=Min(AFileStream.Size-AFileStream.Position,IoHandler.RecvBufferSize);
        //计算需要发送大小,Min()函数在Math单元
        //IoHandler.WriteBufferOpen;//准备发送缓冲
        IoHandler.Write(AFileStream,Asize);
        //IoHandler.WriteBufferClose;
        StatusBar1.Panels[1].Text:=Format('当前文件传输位置%s/大小%d',[cmd,AFileStream.Size]);
        ProgressBar1.Position:=ProgressBar1.Position+ASize;
    end;
end;

end.

转载于:https://my.oschina.net/u/582827/blog/1502362

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值