Delphi DataSnap upload xml file in body

424 Views Asked by At

in delphi 10 with the Datasnap component I am trying to declare a Post method that receives an XML file but I can't.

Does anybody know if Datasnap only can receive Json format type in the body?

(in contrary any example will be great)

Thanks in advance.

2

There are 2 best solutions below

0
guetlaur On

You can overcome this with your datasnap WebModuleUnit and your custom ufileUploader unit like this :

  1. In WebModuleUnit :
    procedure TWebModule1.WebModuleDefaultAction(Sender: TObject;
      Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
    begin
      if Request.InternalPathInfo.StartsWith('/UploadFile') then
        Response.Content := ufileUploader.UploadFile(Request)
      else if (Request.InternalPathInfo = '') or (Request.InternalPathInfo = '/')
      then
        Response.Content := ReverseString.Content
      else
        Response.SendRedirect(Request.InternalScriptName + '/');
    end;
  1. in your ufileUploader unit :
    unit ufileUploader;
    
    interface
    
    uses Web.HTTPApp;
    
    function UploadFile(ARequest: TWebRequest): string;
    
    implementation
    
    uses System.SysUtils, System.Classes, Web.ReqMulti;
    
    function UploadFile(ARequest: TWebRequest): string;
    const
      DestPath = 'c:\';
    var
      i: integer;
      LFileName: string;
      LStream: TMemoryStream;
    begin
      if not TMultipartContentParser.CanParse(ARequest) then
      begin
        Result := 'Cannot parse request';
        Exit;
      end;
      if ARequest.Files.Count < 1 then
      begin
        Result := 'No file sended';
        Exit;
      end;
      LStream := TMemoryStream.Create;
      try
        // You have sended ARequest.Files.Count files
        for i := 0 to ARequest.Files.Count - 1 do
        begin
          LFileName := string(ARequest.Files.Items[i].FileName);
          LStream.Clear;
          // Read the sended file stream
          LStream.CopyFrom(ARequest.Files.Items[i].Stream,
            ARequest.Files.Items[i].Stream.Size);
          LStream.Position := 0;
          // Do what you want with the stream
          LStream.SaveToFile(DestPath + LFileName);
        end;
        Result := Format('%d files saved to %s ', [ARequest.Files.Count, DestPath]);
      finally
        FreeAndNil(LStream);
      end;
    end;
    
    end.

0
SiBrit On

This is not the answer you are hoping for, but I opened a case with Embarcadero for this exact problem and their response was:

Hello

My name is Steve Axtell. I am looking at this case.

I am sorry but Datasnap does not support XML. It only supports JSON, hence the error message.

Regards

Steve Axtell Embarcadero Support ref:_00D30HwR._5005a28Y6yq:ref

The problem is in Datasnap.DSService.TDSRESTService.ProcessParameters:

// Look for more parameters in the body
if (Content <> nil) and (Length(Content) > 0) then
begin
  if LBody = nil then
  begin
    LBodyArray := nil;
    LBody := TJSONObject.ParseJSONValue(Content, 0);
    LFreeBody := LBody;
    if LBody = nil then
    begin
      //ParamArray.Free;
      raise TDSServiceException.Create(SNoJSONValue);
    end;
    if (LBody is TJSONObject) and (TJSONObject(LBody).Count = 1) and
      (TJSONObject(LBody).Pairs[0].JSonString.Value = PARAMETERS_PAIR) and
      (TJSONObject(LBody).Pairs[0].JsonValue is TJSONArray) then
    begin
      LBodyArray := TJSONArray(TJSONObject(LBody).Pairs[0].JsonValue);
      LBodyArrayIndex := 0;
    end
  end;
end;

If the body is not in JSON, it fails to process the REST request, and I've not found a way to force DataSnap to not look in the body for additional parameters.

Note that in my case, I'm not using TComponent but TDataModule for the server methods.