使用CGI运行Delphi应用程序并将结果发送到前端

使用CGI运行Delphi应用程序并将结果发送到前端,delphi,cgi,intraweb,Delphi,Cgi,Intraweb,我有一个返回图像的winCGI可执行脚本。我使用Intraweb作为服务器 我有一个用delphi制作的自定义web服务器,我创建了一个函数来运行cgi并返回图像 cgi来自第三方,我无法更改您的代码。 当我查询图像时,CGI返回下一个代码: 'Content-type: image/gif'#$A'Access-Control-Allow-Origin: *'#$A#$A'GIF89a@'#1'@'#1#0#0#0'!ÿ'#$B'NETSCAPE2.0'#3#1'ÿÿ'#0'!ù'#4#0'!

我有一个返回图像的winCGI可执行脚本。我使用Intraweb作为服务器

我有一个用delphi制作的自定义web服务器,我创建了一个函数来运行cgi并返回图像

cgi来自第三方,我无法更改您的代码。 当我查询图像时,CGI返回下一个代码:

'Content-type: image/gif'#$A'Access-Control-Allow-Origin: *'#$A#$A'GIF89a@'#1'@'#1#0#0#0'!ÿ'#$B'NETSCAPE2.0'#3#1'ÿÿ'#0'!ù'#4#0'!'#0#0#0','#0#0#0#0'@'#1'@'#1'‡'#0#0#0#1#1#1#2#2#2#3#3#3#4#4#4#5#5#5#6#6#6#7#7#7#8#8#8#9#9#9#$A#$A#$A#$B#$B#$B#$C#$C#$C#$D#$D#$D#$E#$E#$E#$F#$F#$F#$10#$10#$10#$11#$11#$11#$12#$12#$12#$13#$13#$13#$14#$14#$14#$15#$15#$15#$16#$16#$16#$17#$17#$17#$18#$18#$18#$19#........
我需要将图像发送到浏览器中的前端应用程序

<div>
 <img src="getImage(1)">
</div>

这里,getImage函数从服务器获取图像,但没有显示,因为我认为将图像从服务器返回到前端的格式有问题。 如何将服务器上图像的内容文本修复为前端的有效图像

function RunCGIOutput(CommandLine: string; Stream:TStream;Folder: string = ''): string;
const
  CReadBuffer = 2400;
var
  saSecurity: TSecurityAttributes;
  hRead: THandle;
  hWrite: THandle;
  suiStartup: TStartupInfo;
  piProcess: TProcessInformation;
  dRead: DWORD;
  Handle,WasOK:Boolean;
  Buffer: array[0..CReadBuffer] of AnsiChar;
  BytesRead: Cardinal;
  WorkingDirP,EnvBlock:PChar;

begin
  saSecurity.nLength := SizeOf(TSecurityAttributes);
  saSecurity.bInheritHandle := true;
  saSecurity.lpSecurityDescriptor := nil;
  EnvBlock := BuildEnvBlock(True);
  if Folder <> '' then WorkingDirP := PChar(Folder)
  else WorkingDirP := nil;
  if CreatePipe(hRead, hWrite, @saSecurity, 0) then
    try
      FillChar(suiStartup, SizeOf(TStartupInfo), #0);
      suiStartup.cb := SizeOf(TStartupInfo);
      suiStartup.hStdInput := hRead;
      suiStartup.hStdOutput := hWrite;
      suiStartup.hStdError := hWrite;
      suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
      suiStartup.wShowWindow := SW_HIDE;
      Handle:=CreateProcess(nil, PChar(CommandLine), @saSecurity, @saSecurity, true, CREATE_UNICODE_ENVIRONMENT, EnvBlock, WorkingDirP, suiStartup,
        piProcess);

    CloseHandle(hWrite);
    if Handle then
      try
        repeat
              WasOK := ReadFile(hRead, Buffer, CReadBuffer, BytesRead, nil) and (BytesRead>0);
              if WasOK then
                Stream.WriteBuffer(Buffer, BytesRead);
        until not WasOK;
        WaitForSingleObject(piProcess.hProcess, INFINITE);
      finally
        CloseHandle(piProcess.hThread);
        CloseHandle(piProcess.hProcess);
      end;
  finally
    CloseHandle(hRead);
    StrDispose(EnvBlock);
  end;
end;


//Run CGI, take image and send to browser
function TContentImaqge.Execute(aRequest: THttpRequest; aReply: THttpReply;
  const aPathname: string; aSession: TIWApplication;
  aParams: TStrings): boolean;
var
  s,wresult,saida,LocalDoc:string;
  i:integer;
  Stream:TMemoryStream;
begin
    Result:=True;
    LocalDoc:=TIWAppInfo.GetAppPath + 'wwwroot\cgi-bin\newweb\dgate.exe';
    Stream:=TMemoryStream.Create;
    saida:=RunCGIOutput(LocalDoc,Stream,TIWAppInfo.GetAppPath + 'wwwroot\cgi-bin\newweb\');
    Stream.Position:=0;
    saida:=ReadStringFromStream(Stream, -1, IndyTextEncoding_OSDefault);
    with aReply do
     begin
       ResetReplyType;
       Code := 200;
       ContentType := MIME_GIF; // MIME_HTML;
       SendStream(Stream);
    end;
end;
函数RunCGIOutput(命令行:string;流:TStream;文件夹:string=''):string;
常数
CReadBuffer=2400;
变量
saSecurity:t安全属性;
线程:THandle;
作者:唐德尔;
启动:TStartupInfo;
piProcess:tprocess信息;
恐惧:德沃德;
句柄,WasOK:Boolean;
Buffer:AnsiChar的数组[0..CReadBuffer];
拜特斯拉德:红衣主教;
工作指令,环境块:PChar;
开始
saSecurity.nLength:=SizeOf(TSecurityAttributes);
saSecurity.bInheritHandle:=真;
saSecurity.lpSecurityDescriptor:=nil;
EnvBlock:=BuildEnvBlock(True);
如果是文件夹“”,则WorkingDirP:=PChar(文件夹)
else WorkingDirP:=nil;
如果CreatePipe(hRead,hWrite,@saSecurity,0),则
尝试
FillChar(suiStartup,SizeOf(TStartupInfo),#0);
suiStartup.cb:=SizeOf(TStartupInfo);
suiStartup.hStdInput:=线程;
sui startup.hst输出:=hWrite;
suiStartup.hStdError:=hWrite;
suiStartup.dwFlags:=STARTF_USESTDHANDLES或STARTF_USESHOWWINDOW;
suiStartup.wShowWindow:=SW_HIDE;
句柄:=CreateProcess(nil,PChar(命令行),@saSecurity,@saSecurity,true,CREATE\u UNICODE\u环境,EnvBlock,WorkingDirP,suiStartup,
过程);
闭合手柄(hWrite);
如果处理那么
尝试
重复
WasOK:=ReadFile(hRead、Buffer、CReadBuffer、BytesRead、nil)和(BytesRead>0);
如果可以的话
Stream.WriteBuffer(缓冲区,字节读取);
直到不好;
WaitForSingleObject(piProcess.hProcess,无限);
最后
CloseHandle(piProcess.hThread);
CloseHandle(piProcess.hproces);
结束;
最后
CloseHandle(线程);
StrDispose(EnvBlock);
结束;
结束;
//运行CGI,拍摄图像并发送到浏览器
函数TContentImaqge.Execute(aRequest:THttpRequest;aReply:THttpReply;
常量名称:字符串;会话:TIWAApplication;
aParams:TStrings):布尔值;
变量
s、 wresult,saida,LocalDoc:string;
i:整数;
流:TMemoryStream;
开始
结果:=真;
LocalDoc:=TIWAppInfo.GetAppPath+'wwwroot\cgi-bin\newweb\dgate.exe';
Stream:=TMemoryStream.Create;
saida:=RunCGIOutput(LocalDoc、Stream、TIWAppInfo.GetAppPath+'wwwroot\cgi-bin\newweb\');
流位置:=0;
saida:=ReadStringFromStream(流,-1,IndyTextEncoding\u OSDefault);
与阿雷普利多
开始
重置回复类型;
代码:=200;
ContentType:=MIME_GIF;//MIME_HTML;
SendStream(Stream);
结束;
结束;
您的模块生成的原始数据应由您的IW内容处理程序按原样传输。响应消息包括:

  • 状态行
  • HTTP头行
  • 分隔标题和正文的空行
  • 主体(案例中的实际图像数据)
  • IntraWeb的
    THTTPReply
    似乎无法控制原始HTTP响应。它提供了专用的界面,可以分别处理状态、标题和正文。这就是为什么您需要预处理从CGI返回的流,并通过空行将头和正文分开。然后您可以通过
    THTTPReply
    传输它们。也许您还希望只将一些标题列为白名单,而忽略其他标题

    在代码段中,您使用了
    ReadStringFromStream
    ,这是毫无意义的,因为您无论如何都会放弃返回值。它将
    Stream
    的位置移动到流的末尾,但这并不重要,因为
    aReply.SendStream(Stream)
    从一开始就发送整个流内容

    另一点是,您使用
    IndyTextEncoding\u OSDefault
    作为
    ReadStringFromStream
    的最后一个参数,这可能是错误的,因为因此您应该使用
    IndyTextEncoding\u ASCII

    请尝试以下代码:

    function TContentImaqge.Execute(aRequest: THttpRequest; aReply: THttpReply;
      const aPathname: string; aSession: TIWApplication;
      aParams: TStrings): Boolean;
    var
      CGIOutput, ContentStream: TMemoryStream;
      LocalDoc, Line: string;
      CharPos: Integer;
    begin
      Result := True;
      CGIOutput := TMemoryStream.Create;
      try
        LocalDoc := TIWAppInfo.GetAppPath + 'wwwroot\cgi-bin\newweb\dgate.exe';
        RunCGIOutput(LocalDoc, CGIOutput, TIWAppInfo.GetAppPath + 'wwwroot\cgi-bin\newweb\');
    
        if ReadLnFromStream(CGIOutput, Line, -1, IndyTextEncoding_ASCII) then
        begin
          { process status line }
          CharPos := Pos(' ', Line);
          if CharPos > 0 then
          begin
            aReply.Code := StrToInt(Copy(Line, CharPos + 1, 3));
            CharPos := Pos(' ', Line, CharPos);
            if CharPos > 0 then
              aReply.CodeText := Copy(Line, CharPos + 1);
          end;
    
          { process headers (copy headers as they are) }
          while ReadLnFromStream(CGIOutput, Line, -1, IndyTextEncoding_ASCII) and (Line <> '') do
            aReply.Headers.Add(Line);
    
          { at this point CGIOutput.Position is at the beginning of body, so let's just copy
            the content to a separate memory stream }
          ContentStream := TMemoryStream.Create;
          try
            ContentStream.CopyFrom(CGIOutput, CGIOutput.Size - CGIOutput.Position);
          except
            ContentStream.Free;
            raise;
          end;
          aReply.SendStream(ContentStream);
        end
        else
        begin
          aReply.Code := 500;
          aReply.CodeText := RSHTTPInternalServerError;
          aReply.WriteString('CGI module returned malformed response.');
        end;
      finally
        CGIOutput.Free;
      end;
    end;
    
    函数TContentImaqge.Execute(aRequest:THttpRequest;aReply:THttpReply;
    常量名称:字符串;会话:TIWAApplication;
    aParams:TStrings):布尔值;
    变量
    CGIOutput,ContentStream:tmememoryStream;
    LocalDoc,行:string;
    CharPos:整数;
    开始
    结果:=真;
    CGIOutput:=TMemoryStream.Create;
    尝试
    LocalDoc:=TIWAppInfo.GetAppPath+'wwwroot\cgi-bin\newweb\dgate.exe';
    RunCGIOutput(LocalDoc、CGIOutput、TIWAppInfo.GetAppPath+'wwwroot\cgi-bin\newweb\');
    如果ReadLnFromStream(CGIOutput,第-1行,IndyTextEncoding\u ASCII)则
    开始
    {进程状态行}
    CharPos:=Pos(“”,行);
    如果CharPos>0,则
    开始
    aReply.Code:=stroint(复制(行,字符+1,3));
    CharPos:=Pos(“”,行,CharPos);
    如果CharPos>0,则
    aReply.CodeText:=副本(行,字符位置+1);
    结束;
    {进程头(按原样复制头)}
    而ReadLnFromStream(CGIOutput,第-1行,IndyTextEncoding_ASCII)和(第“”行)执行
    aReply.Headers.Add(行);
    {在这一点上,CGIOutput.Position在body的开头,所以让我们复制一下
    将内容添加到单独的内存流}
    ContentStream:=TMemoryStream.Create;
    尝试
    CopyFrom(CGIOutput,CGIOutput.Size-CGIOutput.Position);
    除了
    ContentStream.Free;
    提高;
    结束;
    aReply.SendStream(ContentStream);
    结束
    其他的
    开始