如何使用indy将文件从服务器发送到客户端

时间:2018-04-28 18:30:19

标签: delphi indy

我找一个例子,如何从服务器接收文件(我使用Indy) 我想向服务器发送一些需求

在客户端:

MyIdTCPClient.IOHandler.WriteLn('SEND_FILE');
MyIdTCPClient.IOHandler.WriteLn('1.XLS');

在服务器上

procedure TServerMainForm.IdTCPServerExecute(AContext: TIdContext); 
var AStream : TMemoryStream;
    filesize : Integer;
    line, filename: String;
begin

    line := AContext.Connection.IOHandler.ReadLn();
        if line = 'SEND_FILE' then
        begin
            filename := AContext.Connection.IOHandler.ReadLn();

            AStream := TIdFileStream.Create(filename, fmOpenRead + fmShareDenyNone);
           try
               AContext.Connection.IOHandler.Write('FILE_DOWNLOAD'); //send command "FILE"
               AContext.Connection.IOHandler.Write(ExtractFilename(filename)); // send file name
               AContext.Connection.IOHandler.Write(IntToStr(AStream.Size)); //send file size

               AContext.Connection.IOHandler.Write(AStream);
           finally
               FreeAndNil(AStream);

           end;

然后在客户端

if MyIdTCPClient.IOHandler.InputBufferIsEmpty then
  begin
    MyIdTCPClient.IOHandler.CheckForDataOnSource(10);
    if MyIdTCPClient.IOHandler.InputBufferIsEmpty then Exit;
  end;
  S := MyIdTCPClient.IOHandler.ReadLn();

  if S = 'FILE_DOWNLOAD' then
  begin
        MyIdTCPClient.IOHandler.LargeStream := True; 

        if MyIdTCPClient.IOHandler.InputBufferIsEmpty then
        begin
          MyIdTCPClient.IOHandler.CheckForDataOnSource(10);
          if MyIdTCPClient.IOHandler.InputBufferIsEmpty then Exit;
        end;

         Filename :=  MyIdTCPClient.IOHandler.ReadLn(); //filename
            S := MyIdTCPClient.IOHandler.ReadLn(); // filesize
            FileSize := StrToInt(S);
            AStream := TIDFileStream.Create(ExtractFilePath(Paramstr(0)) + '\XLS\' + Filename, fmCreate);
            try
                AContext.Connection.IOHandler.ReadStream(AStream, Filesize, False);
            finally
                FreeAndNil(AStream);
            end;

但它不起作用。 任何文件都不是在客户端上创建的; 你能救我吗?

1 个答案:

答案 0 :(得分:4)

发送import './Home.css'; import React, { Component } from 'react'; import Moment from 'react-moment'; export default class Home extends Component { render() { var date = new Date(); const together = "2017-05-14T06:30"; return ( <div> <p><Moment interval={1000} diff={together} unit="seconds">{date}</Moment> Seconds</p> <p><Moment diff={together} unit="minutes">{date}</Moment> Minutes</p> <p><Moment diff={together} unit="days">{date}</Moment> Days</p> <p><Moment diff={together} unit="months">{date}</Moment> Months</p> <p><Moment diff={together} unit="years" decimal>{date}</Moment> Years</p> </div> ); } } 回复时,服务器正在调用FILE_DOWNLOAD而不是IOHandler.Write(String)来发送IOHandler.WriteLn()和文件名字符串。字符串不会以FILE_DOWNLOAD终止,但客户端正在使用CRLF来读取这些字符串。所以它永远不会达到它试图创建文件并读入它的程度。

话虽如此,我建议为您的协议和代码提供一种稍微替代的设计。

您不需要在自己的行上发送文件名。它们应与它们所属的命令位于同一行。

ReadLn()TIdIOHandler.Write(TStream)可以为您处理发送/读取流大小。您不需要手动发送/读取大小,当然也不需要作为字符串。

请改为尝试:

客户端

TIdIOHandler.ReadString()

服务器

var
  XLSFolder: string;

...

MyIdTCPClient.IOHandler.WriteLn('SEND_FILE 1.XLS');

...

if MyIdTCPClient.IOHandler.InputBufferIsEmpty then
begin
  MyIdTCPClient.IOHandler.CheckForDataOnSource(10);
  if MyIdTCPClient.IOHandler.InputBufferIsEmpty then Exit;
end;
S := MyIdTCPClient.IOHandler.ReadLn();
Cmd := Fetch(S);
if Cmd = 'FILE_DOWNLOAD' then
begin
  AStream := TFileStream.Create(XLSFolder + S, fmCreate);
  try
    MyIdTCPClient.IOHandler.LargeStream := True;
    MyIdTCPClient.IOHandler.ReadStream(AStream, -1, False);
  finally
    AStream.Free;
  end;
end;

...

initialization
  XLSFolder := ExtractFilePath(Paramstr(0)) + 'XLS\';