6
$\begingroup$

Would someone example why my hello-world example is not working:

t = Thumbnail@ExampleData[{"TestImage", "Lena"}];
With[{cloudobject = 
   FileNameJoin[{$CloudRootDirectory, "FactorIntegerAPI"}]}, 
 CloudDeploy[
   APIFunction[{"x" -> "Image"}, ImageEffect[#x, "Charcoal"] &], 
   cloudobject, Permissions -> "Public"]
  URLFetch[URLBuild[cloudobject, {"x" -> t}]]]

It gives the following URI too long error:

enter image description here

Does anyone know the rate/size limitations on images for API functions and how to properly encode them?

$\endgroup$
6
$\begingroup$

If you call the API with the image encoded as a URL parameter there will be image size limitations. The solution is to instead post multipart/form-data to the API:

With[{cloudobject = FileNameJoin[{$CloudRootDirectory, "ImageEffectAPI"}]}, 
   CloudDeploy[
      APIFunction[{"x" -> "Image"},
         ImageEffect[#x, "Charcoal"] & ], 
      cloudobject, Permissions -> "Public" ];
   ToExpression[
      URLFetch[cloudobject,
         "Method" -> "POST", 
         "MultipartElements" ->
            {{"x", "image/jpeg"} ->
               ExportString[ExampleData[{"TestImage", "Lena"}], "JPEG"] } ] ] ]

Lena ImageEffect Request MultipartFormData API

The above solution deploys exactly the same API that the question proposes and returns a byte RawArray image string. The final image is generated by applying ToExpression to the RawArray string. It is perhaps preferable to deploy a slightly modified API, which returns a Base64 encoded image instead of a RawArray string:

APIFunction[{"x" -> "Image"}, 
   ExportString[
      ImageEffect[#x, "Charcoal"], {"Base64", "JPEG"}] & ]

Deploy and call this API exactly as above, but instead of ToExpression apply ImportString to the result:

ImportString[URLFetch[cloudobject, ... ], {"Base64", "JPEG"}]

Comment:

The documentation that an APIFunction can accept multipart/form-data is to say the least a bit tenuous: The APIFunction documentation mentions in the last Details and Options bullet that this function “allows the same options as FormFunction” and under Properties & Relations that the “APIFunction is designed to be interchangeable with FormFunction.” A FormFunction example in the Scope section gives an image file picker. From this one might guess that a FormFunction can accept multipart/form-data and that an APIFunction also can. After intercepting some FormFunction HTTP traffic and a bit of experimentation with URLFetch, the solution presented in this answer should in retrospect seem obvious.

$\endgroup$
  • $\begingroup$ Can you add how one would curl this api? @ChristopherHaydock $\endgroup$ – M.R. Nov 27 '18 at 23:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.