Grabbing partial data from the clipboard in javascript

Viewed 459

I have copied an Excel table which is about a million rows. When I look at the clipboard on my system, it seems to contain about 250MB of data. However, I only need to grab the styling information from it, for example:

enter image description here

This entire data comes out to (far) less than 1MB of data. Is there a way to read the clipboard as if it were a file or stream, so that I can just do, for example:

clipboard.read(1024)

Otherwise, if I do the straight:

evt.clipboardData.getData('text/html')

And grab the section of data I want after getting the data, it takes me over 10 seconds to do! Whereas I believe the event should only take 0.1s or so, if I'm able to read the clipboard data in a partial manner, as if it were a file.

What can I do here? Is it possible to use FileReader on the clipboard? If so, how could that be done?

2 Answers

The Clipboard.read API cited in the comments can return clipboard contents as a list of ClipboardItem objects, from which you can then obtain a Blob object, which you can then .slice to perform partial reads. (The MDN claims that Clipboard.read returns a DataTransfer object, but this disagrees with the specification, so I assume this is stale information, or simply in error.)

const perm = await navigator.permissions.query({ name: 'clipboard-read' });
switch (perm.state) {
case 'granted':
case 'prompt':
    break;
default:
    throw new Error("clipboard-read permission not granted");
}

const items = await navigator.clipboard.read();
for (const item of items) {
    const blob = await item.getType('text/html');
    const first1M = await blob.slice(0, 1048576).arrayBuffer();
    
    /* process first1M */
}

However, the Clipboard API is nowhere near universally available as of yet. Firefox ESR 78.9 doesn’t implement it, and by the state of MDN it hardly seems to be on Mozilla’s radar at all. (I haven’t tried other browsers yet; perhaps in Chrome it’s already usable.)

After a lot a research, this is not possible in Javascript, there is no support for stream manipulation using the clipboard object so u have to read the entire content at once.

However, u can use MacOS (inferred from your picture) native tools for processing the clipboard data: pbcopy and pbpaste, and they are extremely fast, orders of magnitude faster than Javascript, so u can delegate the heavy processing of the text to them.

So, after u copy the 250MB of text, you can slice it and read only the first n bytes (in this case 1024) and substitute the content of the clipboard with that, so now u it will be available for u to use it in Javascript:

pbpaste | cut -b 1-1024 | pbcopy

If u need any documentation about each terminal command, u can run man command_name. Extracting the first 1024 bytes of the clipboard took less than a second with this approach.

I tested it with a sample text file of 390MB created with python with this script:

c = 30000000

with open('sample.txt', 'w') as file:
    file.writelines('a sample code' for i in range(c))
Related