【问题标题】:TIdHTTPServer with TIdMultiPartFormDataStreamTIdHTTPServer 与 TIdMultiPartFormDataStream
【发布时间】:2012-06-29 01:48:57
【问题描述】:

这与我之前的问题 here 有关,我发现了一个东西,认为这可能是我的问题的解决方案,但我无法让它工作,我需要有人可以帮助我。

这是代码
代码 TIdMIMEBoundary.FindBoundary() 的问题是未声明的标识符以及 Fetch()。

uses
...
IdTCPConnection, IdTCPClient, IdHTTP, IdBaseComponent,
  IdComponent, IdCustomTCPServer, IdCustomHTTPServer, IdHTTPServer,
  IdContext, IdMultipartFormData, IdHeaderList, IdMessageCoder,
  IdMessageCoderMIME, IdMessage, IdGlobalProtocols;


procedure DecodeFormData(const Header: String; ASourceStream:TStream);
var
  MsgEnd: Boolean;
  Decoder: TIdMessageDecoder;
  Tmp: String;
  Dest: TStream;
begin
  MsgEnd := False;
  Decoder := TIdMessageDecoderMIME.Create(nil);
  try
    TIdMessageDecoderMIME(Decoder).MIMEBoundary :=
    TIdMIMEBoundary.FindBoundary(Header);
    Decoder.SourceStream := ASourceStream;
    Decoder.FreeSourceStream := False;
    Decoder.ReadLn;
    repeat
      Decoder.ReadHeader;
      case Decoder.PartType of
        mcptUnknown:
        raise Exception.Create('Unknown form data detected');

        mcptText:
        begin
          Tmp := Decoder.Headers.Values['Content-Type'];
          Dest := TMemoryStream.Create;
          try
            Decoder := Decoder.ReadBody(Dest,MsgEnd);
            if AnsiSameText(Fetch(Tmp, ';'),'multipart/mixed') then
              DecodeFormData(Tmp, Dest)
             else
            // use Dest as needed...
          finally
            FreeAndNil(Dest);
          end;//try
        end;

      mcptAttachment:
      begin
        Tmp := ExtractFileName(Decoder.FileName);
        if Tmp <>'' then
          Tmp := 'c:\some folder\' + Tmp
        else
          Tmp := MakeTempFilename('c:\somefolder\');
        Dest := TFileStream.Create(Tmp, fmCreate);
        try
          Decoder := Decoder.ReadBody(Dest,MsgEnd);
        finally
          FreeAndNil(Dest);
        end;//try
      end;

      end;

      until (Decoder = nil) or MsgEnd;
  finally
    FreeAndNil(Decoder);
  end;//try
end;

【问题讨论】:

  • 为什么人们会无缘无故地投票?还是因为他们没有答案?
  • 你需要使用 IdMessage ,IdMessageCoderMIME
  • 你需要和IdGlobal一样一周。
  • 只有投反对票的人知道他的原因,但这可能是因为您发布了一个很少或没有上下文的问题,并引用了您之前的问题(这相当于重复发布)。然后,您粘贴了您在互联网上找到的一页半代码,并询问任何人都可以通过搜索 Indy 源文件夹在几分钟内找出丢失的标识符。

标签: delphi indy


【解决方案1】:

您需要在您的 uses 子句中包含 IdMessage 和 IdMessageCoderMIME

【讨论】:

    【解决方案2】:

    我创建了一个名为 TIdMultiPartFormDataStreamReader 的对象,它可以一步解码您在服务器上收到的所有多部分/表单数据内容。

    unit idMultipartFormDataReader;
    
    interface
    
    {$I IdCompilerDefines.inc}
    
    uses System.SysUtils, System.Classes, IdGlobal, IdGlobalProtocols,
      idMultipartFormData, IdCustomHTTPServer,
      IdCoderQuotedPrintable, IdCoderMIME, IdHeaderList;
    
    type
      TIdMultiPartFormDataStreamReader = class( TIdMultiPartFormDataStream )
      private
        FRequestInfo: TIdHTTPRequestInfo;
      protected
        procedure decodeStream;
      public
        property Fields: TIdFormDataFields read FFields;
        constructor Create( ARequestInfo: TIdHTTPRequestInfo );
      end;
    
    implementation
    
    { TIdMultiPartFormDataStreamReader }
    
    constructor TIdMultiPartFormDataStreamReader.Create(
      ARequestInfo: TIdHTTPRequestInfo);
    begin
      inherited Create;
      FSize := 0;
      FInitialized := False;
      FFields := TIdFormDataFields.Create(Self);
      FRequestInfo := ARequestInfo;
      decodeStream;
    end;
    
    procedure TIdMultiPartFormDataStreamReader.decodeStream;
    var
      delimi, cadStream: string;
      cabeceras: TIdHeaderList;
      stInfo: TMemoryStream;
      posIniPost, posFinPost, posIniRetorno: Integer;
      cadenaOri: string;
      fieldName: string;
      fieldFileName: string;
      contentType: string;
      charSet: string;
      transferEnconding: string;
      {$IFDEF STRING_IS_ANSI}
        LBytes: TIdBytes;
      {$ENDIF}
    
      function ReadStringLn( StreamOri: TStream; var cadenaBus: string; char_set: string ): Boolean;
      var
        candidato: Boolean;
        posIniSO: Integer;
        posFinSO: Integer;
        StreamDes: TMemoryStream;
        bleer: Byte;
      begin
    
        candidato := False;
        StreamDes := TMemoryStream.Create;
        posIniSO := StreamOri.Position;
    
        cadenaBus := '';
    
        while ( not candidato ) and ( StreamOri.Position < StreamOri.Size ) do begin
    
          StreamOri.Read( bleer, 1 );
    
          if ( bleer = 13 ) then begin
    
            StreamOri.Read( bleer, 1 );
    
            if ( bleer = 10 ) then  begin
    
              candidato := True;
              posFinSO := StreamOri.Position;
              StreamOri.Position := posIniSO;
    
              if ( posFinSO - 2 - posIniSO > 0 ) then begin
    
                StreamDes.CopyFrom( StreamOri, posFinSO - 2 - posIniSO );
    
                StreamDes.Position := 0;
    
                cadenaBus := IdGlobalProtocols.ReadStringAsCharset( StreamDes, char_set );
    
              end;
    
              StreamOri.Position := posFinSO;
    
            end;
    
          end;
    
        end;
    
    
        StreamDes.Free;
        Result := candidato;
    
      end;
    begin
      {$IFDEF STRING_IS_ANSI}
      LBytes := nil;
      {$ENDIF}
    
      if ( ExtractHeaderItem( FRequestInfo.RawHeaders.Values[ 'Content-Type' ] ) <> 'multipart/form-data' ) then
        Exit;
    
      cabeceras := TIdHeaderList.Create( TIdHeaderQuotingType.QuoteHTTP );
    
      delimi := FRequestInfo.RawHeaders.Params['Content-Type', 'boundary'];
    
      FBoundary := delimi;
    
      FRequestContentType := sContentTypeFormData + FBoundary;
    
      FRequestInfo.PostStream.Position := 0;
    
      if ( ReadStringLn( FRequestInfo.PostStream, cadenaOri, FRequestInfo.CharSet ) ) then begin
    
        while ( cadenaOri = '--' + delimi )  and
              ( FRequestInfo.PostStream.Position < FRequestInfo.PostStream.Size ) do begin
    
          if ( ReadStringLn( FRequestInfo.PostStream, cadenaOri, FRequestInfo.CharSet ) ) then begin
    
            while ( cadenaOri <> '' ) and
              ( FRequestInfo.PostStream.Position < FRequestInfo.PostStream.Size ) do begin
    
              cabeceras.Add( cadenaOri );
              ReadStringLn( FRequestInfo.PostStream, cadenaOri, FRequestInfo.CharSet );
    
            end;
    
            fieldName := cabeceras.Params[ 'Content-Disposition', 'name' ];
            fieldFileName := cabeceras.Params[ 'Content-Disposition', 'filename' ];
    
    
            contentType := ExtractHeaderItem( cabeceras.Values[ 'Content-Type' ] );
            charSet := cabeceras.Params[ 'Content-Type', 'charset' ];
    
            transferEnconding := cabeceras.Values[ 'Content-Transfer-Encoding' ];
    
            stInfo := TMemoryStream.Create;
            posIniPost := FRequestInfo.PostStream.Position;
            posFinPost := posIniPost;
    
            ReadStringLn( FRequestInfo.PostStream, cadenaOri, FRequestInfo.CharSet );
    
            while ( cadenaOri <> '--' + delimi ) and ( cadenaOri <> '--' + delimi + '--' )  and
              ( FRequestInfo.PostStream.Position < FRequestInfo.PostStream.Size ) do begin
    
              posFinPost := FRequestInfo.PostStream.Position;
              ReadStringLn( FRequestInfo.PostStream, cadenaOri, FRequestInfo.CharSet );
    
            end;
    
            posIniRetorno := FRequestInfo.PostStream.Position;
    
            FRequestInfo.PostStream.Position := posIniPost;
    
            if ( posFinPost - 2 - posIniPost > 0 ) then begin
    
              if ( fieldFileName <> '' ) then begin
    
                stInfo.CopyFrom( FRequestInfo.PostStream, posFinPost - 2 - posIniPost );
    
                if ( LowerCase( transferEnconding ) = 'quoted-printable' ) then begin
    
                  stInfo.Position := 0;
    
                  cadStream := ReadStringFromStream( stInfo );
    
                  stInfo.Clear;
                  stInfo.Position := 0;
    
                  TIdDecoderQuotedPrintable.DecodeStream( cadStream, stInfo );
    
                end else if ( LowerCase( transferEnconding ) = 'base64' ) then begin
    
                  stInfo.Position := 0;
    
                  cadStream := ReadStringFromStream( stInfo );
    
                  stInfo.Clear;
                  stInfo.Position := 0;
    
                  TIdDecoderMIME.DecodeStream( cadStream, stInfo );
    
                end;
    
                stInfo.Position := 0;
    
                AddFormField( fieldName, contentType, charSet, stInfo, fieldFileName );
    
              end else begin
    
                stInfo.CopyFrom( FRequestInfo.PostStream, posFinPost - 2 - posIniPost );
    
                cadStream := '';
    
                stInfo.Position := 0;
    
                {$IFDEF STRING_IS_ANSI}
    
                ReadTIdBytesFromStream( stInfo, LBytes, stInfo.Size );
    
                {$ENDIF}
    
                if ( LowerCase( transferEnconding ) = '7bit' ) then begin
    
                  {$IFDEF STRING_IS_UNICODE}
    
                  cadStream := ReadStringFromStream( stInfo, -1, IndyTextEncoding_ASCII );
    
                  {$ELSE}
    
                  CheckByteEncoding( LBytes, IndyTextEncoding_ASCII, CharsetToEncoding( charSet ) );
    
                  {$ENDIF}
    
                end else if ( LowerCase( transferEnconding ) = 'quoted-printable' ) then begin
    
                  {$IFDEF STRING_IS_UNICODE}
    
                  cadStream := ReadStringFromStream( stInfo );
    
                  cadStream := TIdDecoderQuotedPrintable.DecodeString( cadStream, CharsetToEncoding( charSet ) );
    
                  {$ELSE}
    
                  BytesToRaw( LBytes, cadStream, Length( LBytes ) );
    
                  LBytes := TIdDecoderQuotedPrintable.DecodeBytes( cadStream );
    
                  {$ENDIF}
    
                end else if ( LowerCase( transferEnconding ) = 'base64' ) then begin
    
                  {$IFDEF STRING_IS_UNICODE}
    
                  cadStream := ReadStringFromStream( stInfo );
    
                  cadStream := TIdDecoderMIME.DecodeString( cadStream, CharsetToEncoding( charSet ) );
    
                  {$ELSE}
    
                  BytesToRaw( LBytes, cadStream, Length( LBytes ) );
    
                  LBytes := TIdDecoderMIME.DecodeBytes( cadStream );
    
                  {$ENDIF}
    
                end else if ( LowerCase( transferEnconding ) = '8bit' ) or ( LowerCase( transferEnconding ) = 'binary' ) then begin
    
                  {$IFDEF STRING_IS_UNICODE}
    
                  cadStream := ReadStringAsCharset( stInfo, charSet );
    
                  {$ENDIF}
    
                end;
    
                {$IFDEF STRING_IS_ANSI}
    
                BytesToRaw( LBytes, cadStream, Length( LBytes ) );
    
                {$ENDIF}
    
                AddFormField( fieldName, cadStream, charSet, contentType );
    
                stInfo.Free;
    
              end;
    
            end;
    
            FRequestInfo.PostStream.Position := posIniRetorno;
    
            cabeceras.Clear;
    
          end;
    
        end;
    
      end;
    
    end;
    
    end.

    项目在https://github.com/enriquecerda/TIdMultiPartFormDataStreamReader

    【讨论】:

      猜你喜欢
      • 2012-06-17
      • 1970-01-01
      • 2011-05-23
      • 1970-01-01
      • 2011-09-05
      • 1970-01-01
      • 1970-01-01
      • 2019-09-10
      • 1970-01-01
      相关资源
      最近更新 更多