这与我上一个问题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;
答案 0 :(得分:1)
您需要在uses子句中包含IdMessage和IdMessageCoderMIME
答案 1 :(得分:-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