1

I have the problem that I want to crop an image from a HTML canvas and then send this image from the browser to a REST API that expects an image file in the request body. Since I want to have the frontend app as lightweight as possible, the whole thing is written in Vanilla JS and I prefer to use the fetch API.

I have tested the API endpoint with Insomnia, these are parameters that work (getting 200 and expected response) there: Headers:

Content-Type: application/octet-stream
Prediction-Key: abcsomekey

and as file simply some jpeg image file.

The catch is that I tried to use the generated JS code which didn't work (getting 400 "BadRequestImageFormat"):

const dataURL = canvasElement.toDataURL()
    const base64 = dataURL.split(',')[1]
    console.log(base64)
    const options = {
      method: 'POST',
      headers: {
        'Content-Type': 'application/octet-stream',
        'Prediction-Key': 'abcsomekey'
      },
      body: base64,
    };
    
    fetch('https://some.api.com/some/path', options)
      .then(response => response.json())
      .then(response => console.log(response))
      .catch(err => console.error(err));

Also curl didn't work:

curl --request POST \
  --url https://some.api.com/some/path \
  --header 'Content-Type: application/octet-stream' \
  --header 'Prediction-Key: abcsomekey' \
  --data 'somebase64string'

How can I solve this? And as a second step, how can I send only part of the canvas (a cropped part of it) instead of the whole thing?

Matthias Wolf
  • 75
  • 1
  • 1
  • 6
  • It seems the image is first converted to a base64 string. In order to send a string I think `application/octet-stream` won't work because it's for sending files. I could be wrong though but I'd suggest trying `'Content-Type: application/json'` Also it depends on how the REST API is reading the string from input body - can you share that? – long_hair_programmer Oct 01 '22 at 15:35
  • I tried using `'Content-Type: application/json'` but it doesn't work either. The API is directly from Azure so I have no influence or detailed knowledge on how it processes data. I just know that it works when you upload a file manually using e.g. Insomnia. – Matthias Wolf Oct 01 '22 at 16:20

1 Answers1

0

If the body is an ArrayBuffer, it can be posted as the raw HTTP POST body.

With your code and the canvasElement, it would look something like this:

const context = canvasElement.getContext("2d");
const imageData = context.getImageData(x, y, w, h);
const buffer = imageData.data.buffer; // this is an ArrayBuffer

const options = {
    method: 'POST',
    headers: {
        'Content-Type': 'application/octet-stream',
        'Prediction-Key': 'abcsomekey'
    },
    body: buffer,
};
    
fetch('https://some.api.com/some/path', options)
    .then(response => response.json())
    .then(response => console.log(response))
    .catch(err => console.error(err));
sibbl
  • 3,203
  • 26
  • 38