fabriciocolombo / delphi-rest-client-api

A Delphi REST client API to consume REST services written in any programming language.
Apache License 2.0
380 stars 182 forks source link

is it possible to send an binary? #78

Closed Tuldi closed 7 years ago

Tuldi commented 8 years ago

Hello! As the header says I'd like to send a binary (a picture from the HDD) with this library!

The Server wants the binary to be of content_type "multipart/form-data"...

I tried to send the binary as Stream:

FS := TMemoryStream.Create; FS.LoadFromFile('C:\Users\Tuldi\Pictures\15.jpg');

DM.RestClient.Resource('http://172.19.31.138:5540/webcrawler/v1/api/upload') .Accept(RestUtils.MediaType_Json) .ContentType('multipart/form-data') .Post(FS);

I tried to send the binary as String: myObject : TByteArr; myObject := self.ReadIn('C:\Users\vanpatri\Pictures\15.jpg'); SetString(myString, PAnsiChar(@myObject[0]), length(myObject));

DM.RestClient.Resource('http://172.19.31.138:5540/webcrawler/v1/api/upload') .Accept(RestUtils.MediaType_Json) .ContentType('multipart/form-data') .Post(myString);

But I allways get a 500 ERROR and this message: {"Message":"An error has occurred."}

Am I doing something wrong or are binaries not supported? The Content_type i am using is not in the RestUtils.. is this a problem?

Thanks a lot!

greetings Tuldi

RobertoSchneiders commented 8 years ago

@Tuldi I don't have a direct answer, but I will try to help.

The 500 error indicates that it is an error in the server side, you should verify what is the server doing, maybe some problem on the binary parser? If it was a problem with the data you are sending, the server should return a HTTP 422. But we do not always have the luck to consume an api that follows the conventions.

This is your server? If it is, I would try to comment all the server code and just log the request body, to make sure that the problem is on the way the client is sending the data. If it's not, I would try to make the request work using some rest client (Postman) and then compare the request with the RestClient one.

I'm not sure if passing the memory stream object (FS) is the same as pass the image binary to the Post method, are you?

Am I doing something wrong or are binaries not supported?

I'm not sure. I don't recall having sent a binary with this library, but I think it should work.

The Content_type i am using is not in the RestUtils.. is this a problem?

No, it should work just fine.

Tuldi commented 7 years ago

Hello Roberto! I am still (or again) trying to send a binary (a picture) to a service! As suggested I tried to send requests with the postmaster.... ordinary get post put request i got to work with your library and also with the postmaster!

But the upload i could not get to work!

But with the fiddler Client i could upload a picture... so the service should not be the problem.

The Request when i create it with the Fiddler looks like:

POST http://172.19.31.138:5540/webcrawler/v1/api/upload HTTP/1.1 Content-Type: multipart/form-data; boundary=-------------------------acebdf13572468 Host: 172.19.31.138:5540 Content-Length: 111012

---------------------------acebdf13572468 Content-Disposition: form-data; name="fieldNameHere"; filename="csm_peru-bolivien-chile_d921c496b1.jpg" Content-Type: image/jpeg XXXXXXXXXXXXXXXXXXXXXXXXXXXXXBINARYDATAXXXXXXXXXXXXXXXXXXXXXXXXXX ---------------------------acebdf13572468--

I could imagine that when i do the request with following Code:

DM.RestClient.Resource('http://172.19.31.138:5540/webcrawler/v1/api/upload')
.Accept(RestUtils.MediaType_Json)
.ContentType('multipart/form-data')
.Post(myString);

that the "boundary" is missing or wrong....

do you have any idea what i do wrong or i could change?

Or maybe you could even try to send a picture to this adress? the URL is public ;-) http://172.19.31.138:5540/webcrawler/v1/api/upload HTTP/1.1

I'd be very thankfull for every Tip!

thanks a lot! greetings Tuldi unbenannt

RobertoSchneiders commented 7 years ago

Hello,

I guess the problem is the format of you data. It should by base64 encoded. Maybe the Fiddler is transforming the binary on base64 for you. I have a production code that sends an object that contains an image with this library, so, it works. My code looks like this:

var
  ObjectStream, CompactedStream : TStringStream;

begin
  ObjectStream := TStringStream.Create(TJsonUtil.Marshal(ObjectWithMultipleFields));
  CompactedStream := Compact(ObjectStream);

  DM.RestClient.Resource(url)
    .Accept(RestUtils.MediaType_Json)
    .ContentType('gzip/json')
    .Post(CompactedStream);
end

In my case the API supports gzip, so, I'm compacting the json before send, but this is not mandatory.

Could you try something like this?

var
  ImageStream: TStringStream;
begin
  ImageStream := TStringStream.Create(TJsonUtil.Marshal(ImageBinary));
  DM.RestClient.Resource('http://172.19.31.138:5540/webcrawler/v1/api/upload')
    .Accept(RestUtils.MediaType_Json)
    .ContentType('multipart/form-data')
    .Post(ImageStream);
end
Tuldi commented 7 years ago

Hello Roberto!

Thank you very much for your help!

But unfortunately i still got the 'HTTP Error: 415'

Unsupported Media Type! my Code looks like this:

` try FS := TMemoryStream.Create; FS.LoadFromFile('C:\Users\vanpatri\Pictures\15.jpg');

ImageStream := TStringStream.Create(TJsonUtil.Marshal(FS));
DM.RestClient.Resource('http://172.19.31.138:5540/webcrawler/v1/api/upload')
               .Accept(RestUtils.MediaType_Json)
               .ContentType('multipart/form-data')
               .Post(ImageStream);

ShowMessage('OK'); except on E: Exception do ShowMessage(e.Message); //raise Exception.Create('Fehlermeldung'); end; `

Any Ideas?

RobertoSchneiders commented 7 years ago

The Unsupported Media Type error makes clear that the only problem that you have is that you are sending the data in a format that the server does not understand.

This will depends on the server implementation. As far as I can see (in the fiddler request) the server is specting a form-data with a file. This is very strange, shouldn't use form-data for that. The API should receive a image/jpeg content-type.

I don't think this library could send a multipart/form-data content-type, because of the Content-Disposition. I'm not sure how the syntax of the http request would like to be.

If you change your server implementation to accept a image/jpeg content-type everything should be fine.

Tuldi commented 7 years ago

If you change your server implementation to accept a image/jpeg content-type everything should be fine.

you were right ;-)

thank you very much!!