Jump to content
markus_ja

Upload Image to Rest Server

Recommended Posts

Hello,

 

I want to upload an image to my rest server, where it is stored as BLOB in my database.

 

I use the REST[...].Call.Put() function and my image is already in a JFile (JBlob) variable. But I don't know how to convert that data in order to send it properly?

e.g. Send it as byte array or convert it to a base64 string.

 

When I convert it, eg. to an UInt8Array, and pass that data in the put method I get the following error:

 

Uncaught InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.  [line #5928]

  call := REST[FRootURL, PrepareURI(aDestURI)].Call;

  fileReader := JFileReader.Create;
  fileReader.onload :=
    function(event: JEvent): Variant
    begin
      var data: JUint8Array := JUint8Array.Create(JTypedArray(Variant(event.target).result));

      writeln(data.length.tostring);

      call.Put(data);
      result := true;
    end;

  fileReader.readAsArrayBuffer(aBlob);

Share this post


Link to post
Share on other sites

The Put method comes in two versions:

 

    function Put(data: string = ''): TRESTCall; overload;
    function Put(data: JObject): TRESTCall; overload;
 
You should be able to do
 
call.Put(JObject(data));
 
but i have not checked if it works.
 
The error message above seems related to something else.
 
Either headers are set too early or too late, i can't know by the error message (without research).
 
Too early (perhaps not your problem): It [the error] would be emitted during the execution of "Call" (in TRESTCall.Create TW3HttpHeader.SetRequestHeader is called). The Underlying XHTTPRequest object should be in an ok state by then (have not checked, when i think about it i have never used the header functionality like that).
Did you make sure there's no requests in the cache that may have header info?
 
Too late (and i think this may be your problem): In the string version of Put Primoz inserts a header to tell the server this is text data. Then stringifies your JObject. So casting won't help in your original quest. You could perhaps try to stringify yourself or set that header early on (['Content-Type'] := 'application/json' if needed).
 
call.Put(JSON.stringify(data));
 
HTH,
 
/Dany

Share this post


Link to post
Share on other sites

Thanks Dany.

 

I got it work. I had to use FileReader.readAsBinaryString (which is currently not exposed by the wrapper) and encoded it to base64. Then on REST server I decoded the string and converted it into a stream.

 

Here is the code, if someone has a similary issue:

  fileReader := JFileReaderHelper.Create;
  fileReader.onload :=
    function(event: JEvent): Variant
    begin
      var data: string := VarToStr(Variant(event.target).result);

      data := Base64Encoder.Encode(data);

      call.Put(data);
      result := true;
    end;

  fileReader.readAsBinaryString(aBlob);

regarding the error: There is an issue in the RTL. It tries to set an header, before the FHttp object is opend.

function TRESTCall.PUT(data: JObject): TRESTCall;
begin
  FHttp.RequestHeaders['Content-Type'] := 'application/json'; //Throws exception: FHttp must first be opened!
  Result := Send('PUT', JSON.Stringify(data));
end;

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×