Paste multiple files from clipboard not working

Viewed 187

So i noticed everytime i paste some file, if i have more than 1 file on my clipboard area it only pastes 1 file, the others my code just don't process.

Here is the snippet to reproduce, even if i have more than 1 file on clipboard it only inserts 1 item in the array. I'm trying to figure out what is happening. (use image files to test).

const inputFileToBase64 = file => new Promise((resolve, reject) => {
  const reader = new FileReader()
  reader.readAsDataURL(file)

  reader.onload = () => resolve(reader.result)
  reader.onerror = error => reject(error)
})

const getBase64Files = async (items) => {
  const base64Files = []  
  
  for (const item of items) {  
     const base64 = await inputFileToBase64(item.getAsFile())
     
     base64Files.push(base64)
  }
  
  return base64Files
}

document.addEventListener('paste', async (event) => { 
  console.log('pasted')
  const items = event.clipboardData.items
  const files = await getBase64Files(items)
  console.log(files)
})
PASTE HERE

2 Answers

The DataTransferItemList items seems to be consumed as soon as the event loop allows it to; it doesn't wait for a FileReader to read it. So, by the time the first file is read, items is empty.

If you allow the task queue to do its stuff, even with a setTimeout of 0, you lose all files:

  const items = event.clipboardData.items
  await new Promise(resolve => setTimeout(resolve, 0)) //wait 0ms
  const files = await getBase64Files(items) //no items, no files

and that's also happening with the working version of getBase64Files below.

Regardless of the explanation (which one might improve upon), it is always a good idea to start all reading at the same time and await for all to complete:

const getBase64Files = async (items) => {
  const base64Files = []

  await Promise.allSettled(
    Array.from(items).map(
      item => inputFileToBase64(item.getAsFile()).then(
        file => base64Files.push(file)
      )
    )
  )
   
  return base64Files
}

and that works.

Related