user497849
user497849

Reputation:

TIdHTTPServer file upload

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

Answers (5)

user1355041
user1355041

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

Ivan Revelli
Ivan Revelli

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

Stijn Sanders
Stijn Sanders

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

Remy Lebeau
Remy Lebeau

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

LaKraven
LaKraven

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

Related Questions