2012-06-29 191 views
0

這與我以前的問題here有關,我發現一些認爲這可能是我的問題的解決方案,但我無法得到它的工作,我需要有人可以幫助我。TIdHTTPServer與TIdMultiPartFormDataStream

這是代碼
與代碼TIdMIMEBoundary.FindBoundary(問題)是未聲明的標識符,並且還抓取()。

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; 
+2

爲什麼人們downvoting沒有任何理由?或者因爲他們沒有答案? – XBasic3000

+0

您需要使用IdMessage,IdMessageCoderMIME – Hendra

+0

您需要和IdGlobal一樣。 –

回答

1

您需要包括IdMessage和IdMessageCoderMIME在你使用條款

+0

和IdGlobal也是如此。 –

-2

我創建了一個叫做TIdMultiPartFormDataStreamReader的對象,在一個單一的步驟解碼所有您收到您的服務器上的multipart/form-data的內容。

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

相關問題