Reputation:
I'm trying to upload files to a Indy(ver. 10.5.5) TIdHTTPServer.
I've been searching for solutions but no luck thus far, what I've found was for older versions of Indy which were not compatible with the version shipped with Delphi 2010.
What I'm hoping is to achieve simply upload a file using "multipart/form-data" to the server and decode it, simple as that, any help is appreciated.
Upvotes: 6
Views: 6964
Reputation: 127
It seems to me that this is a perennial problem. I have looked at all sorts of proposals on the internet and there is nothing comparable to MsMultipartparser.pas on offer. Sadly, it does not work for Unicode.
Why does not someone a lot smarter than me rewrite MsMultipartparser.pas and save us all an awful lot of trouble?
Indy - does not work.
IPWorks - seems to just give you filename(s) and so on. Can't work out how to get file itself.
Alcinoe - no installation instructions let alone explanation and does not seem to work for XE8 or Delphi 10
I looked at several others but they are all impractical.
Upvotes: 1
Reputation: 363
http://www.synaptica.info/2014/01/31/tidhttpserver-decode-content-type-multipartform-data/
I do a simple multipart upload like this:
used units:
interface
uses
System.SysUtils, System.Classes, Web.Win.Sockets, IdBaseComponent,
IdComponent, IdCustomTCPServer, IdCustomHTTPServer, IdHTTPServer, IdContext,
IdTCPServer,System.Generics.Collections, Data.DB, Datasnap.DBClient,IdHeaderList,idGlobal,
IdIntercept,IdMessage,IdMessageCoderMIME,IdMessageCoder,IdGlobalProtocols;
the code that loop on mime content:
procedure TdmNet.IdHTTPServerCommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
Var
ms : TMemoryStream;
newdecoder, Decoder: TIdMessageDecoder;
boundary, startboundary : String;
msgEnd : Boolean;
tmp : String;
I : Integer;
fname : String;
tsValues : TStringList;
begin
i := 0;
if pos('upload',lowercase(ARequestInfo.Document)) > 0 then
begin
If ARequestInfo.PostStream = nil then
AResponseInfo.ContentText := '<HTML><BODY>unparsed:' + ARequestInfo.UnparsedParams +
'<br>Encoding:' + ARequestInfo.ContentEncoding + ARequestInfo.RawHeaders.Values['Content-Type'] +
'<br>HashCode:' + IntToStr(ARequestInfo.GetHashCode) +
'<br>Params:' + ARequestInfo.Params.Text + ' -->stream nullo<br></BODY><HTML>'
Else
ARequestInfo.PostStream.Position := 0;
msgEnd := False;
boundary := ExtractHeaderSubItem(ARequestInfo.ContentType, 'boundary',QuoteHTTP);
startboundary := '--' + boundary;
repeat
tmp := ReadLnFromStream(ARequestInfo.PostStream, -1, True);
until tmp = startboundary;
decoder := TIdMessageDecoderMIME.Create(nil);
TIdMessageDecoderMIME(decoder).MIMEBoundary := boundary;
tsValues := TStringList.Create;
try
repeat
decoder.SourceStream := ARequestInfo.PostStream;
decoder.FreeSourceStream := false;
decoder.ReadHeader;
inc(I);
case Decoder.PartType of
mcptAttachment,mcptText : begin
ms := TMemoryStream.Create;
ms.Position := 0;
newdecoder := Decoder.ReadBody(ms,msgEnd);
tmp := Decoder.Headers.Text;
fname := decoder.Filename;
decoder.Free;
decoder := newdecoder;
if decoder <> nil then
TIdMessageDecoderMIME(decoder).MIMEBoundary := boundary;
sleep(100);
if fname <> '' then
begin
ms.SaveToFile(fname);
//msgEnd := true;
end
else
begin
ms.SaveToFile(inttostr(i) + '.txt');
end;
ms.Free;
end;
mcptIgnore: Begin
try
FreeAndNil(decoder);
decoder := TIdMessageDecoderMIME.Create(nil);
TIdMessageDecoderMIME(decoder).MIMEBoundary := boundary;
finally
ms.Free;
end;
End;
mcptEOF: begin FreeAndNil(decoder); msgEnd := True end;
end;
until (decoder = nil) or(msgEnd);
finally
if decoder <> nil then
decoder.Free;
end;
AResponseInfo.ContentText := AResponseInfo.ContentText + '</BODY><HTML>';
AResponseInfo.ContentText := '<HTML><BODY>unparsed:' + ARequestInfo.UnparsedParams +
'<br>Encoding:' + ARequestInfo.ContentEncoding + '<br>Conte' + ARequestInfo.RawHeaders.Values['Content-Type'] +
'<br>HashCode:' + IntToStr(ARequestInfo.GetHashCode) +
'<br>Params:' + ARequestInfo.Params.Text + ' -->stream nullo<br></BODY><HTML>';
end
Else
Begin
AResponseInfo.ContentText :=
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> ' + #10#13 +
'<html xmlns="http://www.w3.org/1999/xhtml"> ' + #10#13 +
'<head> ' + #10#13 +
'<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> ' + #10#13 +
'<title>Pagina di prova</title> ' + #10#13 +
'</head> ' + #10#13 +
' ' + #10#13 +
'<body> ' + #10#13 +
'<h1>Test multipart from <a href="www.synaptica.info">Synaptica Srl</a> </h1> <BR><BR> ' + #10#13 +
'<form action="upload" method="post" enctype="multipart/form-data"> ' + #10#13 +
'<p>key ' + #10#13 +
' <input type="text" name="key" id="key" /> ' + #10#13 +
'</p> ' + #10#13 +
'<p>group ' + #10#13 +
' <input type="text" name="group" id="key" /> ' + #10#13 +
'</p> ' + #10#13 +
' ' + #10#13 +
'<label for="file">Filename:</label> ' + #10#13 +
'<label for="file">' + ARequestInfo.Document + '</label> ' + #10#13 +
'<input type="file" name="file" id="file" /> ' + #10#13 +
'<br /> ' + #10#13 +
'<input type="submit" name="submit" value="Submit" /> ' + #10#13 +
'</form></p> ' + #10#13 +
'</body> ' + #10#13 +
'</html> ';
End;
Upvotes: 1
Reputation: 36840
I started xxm as a way to build websites with Delphi, and have scripts with both HTML and Pascal code re-compile with a press of the browser's refresh button after changes made.
It uses a generic interface that 'plugs into' IIS, Apache, Internet Explorer, FireFox, and there's a stand-alone HTTP exe also. The interface exposes IxxmParameterPostFile on a parameter when a file is uploaded.
See demo 4 Upload for an example.
Upvotes: 4
Reputation: 595319
TIdHTTPServer
does not currently support multipart/form-data
submissions natively. That is on the todo list for Indy 11. In the meantime, you have to parse the posted MIME data manually using TIdDecoderMIME
, as mjn suggested. There have been examples of that posted in the Embarcadero and Indy forums before.
Upvotes: 8
Reputation: 5869
Only suitable solution I can find without personally testing (let me know if this doesn't lead you to a working solution for your needs, and I'll fire up XE and produce something more eloquent)
Upvotes: 3