1

How do I receive a file using TRESTClient/TRESTResponse? Currently only able to receive text.

RESTResponse1.Content
Mylon
  • 115
  • 1
  • 2
  • 8
  • You are able to receive only text becuase the response is supposed to be only text. Do a Google search for more info but that set of components can only get a string from the server (like some typical json) and then store the response. – Alberto Miola Nov 07 '17 at 21:55
  • Avoid using TStream for this sort of thing because there are problems with it. It may be least hassle to transfer your file encoded using Base64 as a string and decode it on the client side. – MartynA Nov 07 '17 at 21:55
  • If you need to download an executable, a word file or whatever use Indy or something else. – Alberto Miola Nov 07 '17 at 21:56
  • 1
    If you need to receive binary data in a file, then I would suspect that you shouldn't be using `TRESTClient` at all. This doesn't sound like REST which you're dealing with. REST is meant for *data* exchange ... "data" meaning JSON, XML, or other formats of the sort. All the REST components do in Delphi is to make it "easier" to implement a REST server/client by taking control away from you and limiting that control to only things REST actually requires. Otherwise, you should use just plain HTTP communication. After all, REST is just specific HTTP usage. – Jerry Dodge Nov 07 '17 at 21:57
  • Typically, in a REST response, if it includes file data, one of the members of the response will be a text representation of the file, which can be Base64 encoded data. It's very hard to tell without any information about the response your dealing with. – Dave Nottage Nov 08 '17 at 03:14
  • I do not know if it is possible, inside the json, I need to have field text and field Stream (of file). – Mylon Nov 08 '17 at 03:35
  • The reason I said to avoid using streams is because of issues like this one https://stackoverflow.com/questions/41854631/cant-retrieve-tstreams-bigger-than-around-260-000-bytes-from-a-datasnap-server/41878153#41878153. Use Base64 encoding instead.. – MartynA Nov 08 '17 at 07:30

3 Answers3

3

There is a class in namespace REST.Client that can download binary data: REST.Client.TDownloadURL.DownloadRawBytes

uses REST.Client, IpPeerClient;
<...>
    bStream := TMemoryStream.Create;
    TDownloadURL.DownloadRawBytes(url, bStream);
<...>

You should also use an implementation unit IpPeerClient.

V0d01ey
  • 47
  • 1
  • 6
1

Try this:

A simple PHP Web Service for get a JPG file:

<?php
$path = 'c:\1.jpg'; // file path on server
$data = file_get_contents($path);
$base64 =  base64_encode($data);
$json = array("status" => 1, "info" => $base64);
header('Content-type: application/json');
echo  json_encode($json,JSON_UNESCAPED_UNICODE);

Delphi code for saving JPG file from server:

procedure TForm1.btn1Click(Sender: TObject);
var
  strResponeContnt : string;
  oJSON: TJSONObject;
  aJSON: TJSONArray;
  strImageJSON : string;
  varMemoryString : TMemoryStream;

begin

  restClient1.BaseURL := 'http://test/getfile.php';
  restRequest1.Client := restClient1;
  restRequest1.Response := restResponse1;
  restRequest1.Execute;
  strResponeContnt := restResponse1.Content;
  oJSON := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(strResponeContnt),0) as TJSONObject;
  aJSON := TJSONArray(oJSON.Get('info').JsonValue);

  strImageJSON := deQuotedString(oJSON.Pairs[1].JsonValue.ToString) ;

  varMemoryString := TMemoryStream.Create;

  try
    IdDecoderMIME1.DecodeStream(strImageJSON, varMemoryString);
    varMemoryString.Position := 0;
    varMemoryString.SaveToFile('C:\3.jpg');
  finally
    varMemoryString.Free;
  end;

end;

deQuotedString function:

function TForm1.deQuotedString(Value:String):String;
var
  strtmp : string;
begin
 strtmp := Value;
 delete(strtmp,1,1);
 delete(strtmp,Length(strtmp),1);
 Result := strtmp;

end;

Class variable declaration:

restClient1: TRESTClient;
restRequest1: TRESTRequest;
restResponse1: TRESTResponse;
IdDecoderMIME1: TIdDecoderMIME;

JSON uses Unit:

System.JSON

After all you can download file Directly using other Delphi web controls such as INDY and save it.

Aqil
  • 360
  • 2
  • 16
  • when i try your code i get "image loading failed" message. It's like the delphi (XE10.2) decodeBase64 donc really decode the php (7) base64 encoding. do you have any suggestion ? – ffert2907 Sep 02 '18 at 18:40
0

TRestResponse is not good for binary data.

Use idHTTP.

  mem := TMemoryStream.Create;
  idHttp1.Get('http://localhost/index.php', mem);
  //do something
  mem.free;
Charlie
  • 22,886
  • 11
  • 59
  • 90
  • Easy to say, sure, but I just moved from `TIdHTTP` (which I've always used) to `TRESTClient` (which I've never used before), simply because the server I need to work with has very strict security requirements which Indy falls short of. More specifically, downloading repositories from GitHub. – Jerry Dodge Jun 03 '19 at 19:53