Message Boards Message Boards

sendPhoto using TelegramBot (exporting to multy-part form data format)


I created a telegram-bot and I execute requests to the telegram bot API from Mathematica. You can find full API documentation here. I have a problem with sending image from computer or RAM. I try send photo using this code:

$token = <token> (* string -  bot token from @BotFather *)
$chat = <chat_id> (* string - allowed chat id *)

$api = StringTemplate["`token`"][<|"token" -> $token|>]
$url = URLBuild[{$api, "sendPhoto"}]

dataString = ExportString[Plot[Sin[x], {x, 1, 4}, ImageSize->Tiny], "JPEG"]; 

body = StringTemplate[
Content-Disposition: form-data; name=\"chat_id\"

Content-Disposition: form-data; name=\"photo\";filename=\"photo.jpg\"
Content-Type: image/jpeg

]; (* *)

request[] := 
Method -> "POST", 
"ContentType" -> "multipart/form-data; boundary=WMAsrf456BGe4h", 
"Headers" -> {
"Connection" -> "keep-alive"
"Body" -> body[<|"chat_id" -> $chat, "data" -> dataString|>]

response = URLRead[request[]]

(* Out[..] := HTTPResponse[<<504>>] *)

(* Out[..] := "<html>
<head><title>504 Gateway Time-out</title></head>
<body bgcolor=\"white\">
<center><h1>504 Gateway Time-out</h1></center>
</html>" *)

how to send an image?

POSTED BY: Kirill Belov
1 month ago

I did not manage to solve the problem. But I looked at the full text of the query, which is generated by libraries in other languages. I managed almost exactly to repeat everything, but still I can not send the image.


request := 
    Method -> "POST", 
    "ContentType" -> "multipart/form-date; boundary=QWERTYUIOPASDFGHJKLZXCVBNM", 
    "Headers" -> {
      "Accept" -> "application/json, applcation/xml, text/json, text/x-json, text/javascript, text/xml", 
      "Host" -> "", 
      "Content-Length" -> ToString[StringLength[multipartData]], 
      "Accept-Encoding" -> "gzip, deflate"
    "Body" -> multipartData 

And request-body. important: here the \r\n is used instead of the \n:

multipartData  := 
"Content-Disposition: form-data; name=\"chat_id\"", "\r\n", "\r\n", 

"490138492", "\r\n", 
"Content-Disposition: form-data; name=\"photo\"; filename=\"photo-1.png\"", "\r\n", 
"Content-Type: application/octet-stream", "\r\n", "\r\n", 

ExportString[Plot[Sin[x], {x, 1, 2}, ImageSize -> 5], "PNG"], "\r\n", 


And executing the request:


(* Out[..] := {ok->False,error_code->400,description->Bad Request: there is no photo in the request} *)

Last result the better than response with status-code 504. I indicated all headers and parameters by hand. Why could not the picture upload?

POSTED BY: Kirill Belov
23 days ago

If you look into the Details section of HTTPRequest there is a section starting with "The setting for "Body" can have the following forms:"

Among the possible forms there is one that includes explicit File heads, have you tried that?

A bit further down there is even an example:

image = FindFile["ExampleData/Ocelot.jpg"];
req = HTTPRequest[url, <|"Body" -> {"image" -> File[image]}|>];
URLRead[req, "Body"]
POSTED BY: Carlo Barbieri
22 days ago

Thank you, yes, I tried to do so and, strange as it may seem, it worked. But this works only for a file on disk. Solution - create a temporary file, but how to send it from RAM, I still do not understand.

POSTED BY: Kirill Belov
22 days ago

I had a brief look at the API linked. At this time I can only give you pointers to your issues.

Content-Length is in bytes (should give value in bytes, so server will know when to stop).

I believe the Image needs to be base64 (ASCII) encoded.

500 level errors indicate that some processing went wrong on the server side. But I think this is due to content length and possible image encoding.

POSTED BY: Hans Michel
23 days ago

The length in bytes is right. If you delete this header (content-length) then the result will not unchanged. At the moment there is no difference with the use of base64 and without it. Both of ways returns status code 400 and the message "Bad Request: there is no photo in the request"

POSTED BY: Kirill Belov
22 days ago


dataString = ExportString[ExportString[Plot[Sin[x], {x, 1, 4}, ImageSize->Tiny], "JPEG"], "Base64"];
POSTED BY: Bob Tieman
22 days ago

Group Abstract Group Abstract