You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Indy实现服务器向客户端传输文件?附请求示例

我来帮你补全基于Indy的文件传输完整实现,刚好匹配你给出的客户端请求格式,包含服务器端的文件发送逻辑和客户端的文件接收代码:

完整实现:Indy TCP 服务器向客户端传输文件

服务器端完整处理逻辑

你给出的代码片段可以扩展成包含异常处理、文件校验的完整逻辑,确保传输的可靠性:

procedure TServerMainForm.IdTCPServerExecute(AContext: TIdContext);
var
  AStream: TFileStream;
  FileSize: Int64;
  Line, FileName: String;
begin
  try
    // 读取客户端的请求指令
    Line := AContext.Connection.IOHandler.ReadLn();
    if Line = 'SEND_FILE' then
    begin
      // 读取客户端请求的文件名
      FileName := AContext.Connection.IOHandler.ReadLn();
      
      // 先校验文件是否存在
      if FileExists(FileName) then
      begin
        // 向客户端发送"文件存在"的标识
        AContext.Connection.IOHandler.WriteLn('FILE_FOUND');
        
        // 创建文件流读取本地文件
        AStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
        try
          // 发送文件大小(用Int64支持4GB以上的大文件)
          FileSize := AStream.Size;
          AContext.Connection.IOHandler.WriteInt64(FileSize);
          
          // 发送文件内容,指定发送后不关闭流
          AContext.Connection.IOHandler.WriteStream(AStream, False);
          // 强制刷新缓冲区,确保所有数据发送完成
          AContext.Connection.IOHandler.Flush();
        finally
          AStream.Free;
        end;
      end
      else
      begin
        // 文件不存在时向客户端返回错误标识
        AContext.Connection.IOHandler.WriteLn('FILE_NOT_FOUND');
      end;
    end;
  except
    on E: Exception do
    begin
      // 捕获异常并通知客户端,同时断开异常连接
      AContext.Connection.IOHandler.WriteLn('ERROR: ' + E.Message);
      AContext.Connection.Disconnect;
    end;
  end;
end;

小提示: 如果只处理小文件,也可以把WriteInt64换成WriteInteger,但客户端要对应使用ReadInteger来读取文件大小。

客户端接收文件的完整代码

对应你现有的请求代码,客户端发送请求后需要处理服务器的响应,完成文件接收和保存:

procedure TClientForm.ReceiveFileFromServer(const ServerFileName: String; const LocalSavePath: String);
var
  ServerResponse: String;
  FileSize: Int64;
  SaveStream: TFileStream;
begin
  try
    // 确保客户端已连接服务器
    if not MyIdTCPClient.Connected then
      MyIdTCPClient.Connect;

    // 发送请求指令和文件名(和你现有代码完全匹配)
    MyIdTCPClient.IOHandler.WriteLn('SEND_FILE');
    MyIdTCPClient.IOHandler.WriteLn(ServerFileName);

    // 读取服务器的响应
    ServerResponse := MyIdTCPClient.IOHandler.ReadLn();
    if ServerResponse = 'FILE_FOUND' then
    begin
      // 读取服务器发送的文件大小
      FileSize := MyIdTCPClient.IOHandler.ReadInt64();
      
      // 创建本地文件流用于保存
      SaveStream := TFileStream.Create(LocalSavePath, fmCreate or fmShareDenyWrite);
      try
        // 读取服务器发送的文件内容到本地
        MyIdTCPClient.IOHandler.ReadStream(SaveStream, FileSize, False);
        ShowMessage('文件接收完成!已保存到:' + LocalSavePath);
      finally
        SaveStream.Free;
      end;
    end
    else if ServerResponse = 'FILE_NOT_FOUND' then
    begin
      ShowMessage('服务器上不存在文件:' + ServerFileName);
    end
    else if StartsText('ERROR:', ServerResponse) then
    begin
      ShowMessage('传输出错:' + Copy(ServerResponse, 7, Length(ServerResponse)));
    end;
  except
    on E: Exception do
    begin
      ShowMessage('接收文件失败:' + E.Message);
      if MyIdTCPClient.Connected then
        MyIdTCPClient.Disconnect;
    end;
  end;
end;

调用示例: 如果你要获取服务器上的1.XLS并保存到本地C:\Downloads\1.XLS,可以这样调用:

ReceiveFileFromServer('1.XLS', 'C:\Downloads\1.XLS');

关键注意事项

  • 确保客户端和服务器的IOHandler.ReadLn()使用相同编码,如果要支持中文文件名,需要在两端设置IOHandler.DefStringEncoding := IndyTextEncoding_UTF8;
  • 传输大文件时,可以在服务器端添加进度反馈逻辑(比如定期发送已传输字节数),客户端据此显示进度条提升体验
  • 生产环境建议添加身份校验逻辑,避免非法客户端请求服务器文件

内容的提问来源于stack exchange,提问作者Pele

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:24:51