Search code examples
javascriptcanvasreact-reduxarraybuffer

JS | Issues converting arrayBuffer to Uint8ClampedArray


Today I have an issue where I can't convert an ArrayBuffer to Uint8ClampedArray (imageData) from my server's response.

So for testing, I send to my server blob from a 150*300 image, I convert it to buffer on my back-end then process it, just before I send back data, I log it and see that everything is good (data is what it should be and length is 150*300*4: 180000), so I send it back to my front, consume the response as arrayBuffer, and here things start to mess up: I end up with multiple arrays and when I want to create a new imageData I get errors because my length is no more good.

Here is my code:

export const edit = e => dispatch => {
  let payload = store.getState().image.imageData
  payload = payload[payload.length-1]
  const id = e.target.id ? e.target.id : e.target.parentElement.id;
  console.log(payload)
  const meta = {
    width: payload.width,
    height: payload.height
  }
  const formData = new FormData();
  formData.append("meta", JSON.stringify(meta));
  formData.append("data", new Blob([payload.data.buffer]))
  console.log(...formData)
  fetch(`/api/editing/${id}`, {
    method: "POST",
    body: formData
  })
  .then(res => res.arrayBuffer())
  .then(buffer => {
    console.log(buffer)
    const data = new Uint8ClampedArray(buffer)
    console.log(data.length)
    console.log(data)
    const newImg = new ImageData(data, payload.width, payload.height)
    return newImg
  })
  .then(img => {
    const ctx = document.getElementById('canvas').getContext('2d')
    console.log(img)
    ctx.putImageData(img, 0, 0)
  })
  .catch(err => console.log(err))

It's been 4 days i'm stuck on this and i can't find anything online that could help me, i olso tried a ton of things but none of them is working.

I would appreciate any help

EDIT:

my back end:

router.post('/:type', (req, res) => {
  let form = new formidable.IncomingForm()
  form.parse(req, (err, fields, files) => {
    fs.readFile(files.data.path, (err, data) => {
      const imgProcessed = traitement[req.params.type](data)
      console.log(imgProcessed.length)
      return res.status(200).json(imgProcessed)
    })
  })
})

response network tab:

{type: "Buffer",…}
data: [255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,…]
type: "Buffer"

Solution

  • You're sending JSON:

    return res.status(200).json(imgProcessed)
    

    That means you're sending text, not binary data.

    You probably wanted to send just the data:

    return res.status(200).send(imgProcessed)
    // --------------------^^^^
    

    I'm assuming imgProcessed is a Buffer; if not you want to make it one. See the Express.js documentation for send. (It will handle sending the Content-Type: application/octet-stream header for you when you give it a Buffer.)