Search code examples
javascriptangulartypescriptclipboardclipboarddata

Get image (using paste) from the browser


There are two ways to copy an image through the browser (for example chrome), the copy image and the copy address of the image.

When I copy the image address and paste it using my paste Image button, I can get the image copied from the base64 browser. But when I copy the image, I can't get the image. Is there a way to obtain the image using the image coipar, as shown in the examples?

Demo

code

  clickPaste() {
    let self = this;
    (navigator as any).clipboard.readText().then(clipboard => self.clip = clipboard);
console.log(self.clip) // copy image adress ---> base64
  }

Example copy image address - working image

image

Example copy image - does not work

image3

imag4

I know that copying the image and copying the image's address are different things, but I couldn't find out how I can get the image (blob or base64) when I use copy the image.


Solution

  • You can access it from the paste ClipboardEvent's .clipboardData DataTransfer.

    It will be in the .files FileList if available:

    document.onpaste = (evt) => {
      const dT = evt.clipboardData || window.clipboardData;
      const file = dT.files[ 0 ];
      console.log( file );
    };
    img{ height: 100vh; }
    <div contenteditable>You can paste the image here</div>
    <figure>
      <figcaption>Copy this image</figcaption>
      <img src="https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png">
    </figure>

    If you need to get it outside of such an event, then you will need to use the asynchronous Clipboard API.
    Unfortunately, this API is not yet very well supported (currently Blink only), but anyway, here is how you can read an image file using this API.

    You first need to request / check for the "clipboard-read" Permission.
    Then if the request has not be denied, you can try to read the whole content of the clipboard by calling navigator.clipboard.read(). This will return a DataTransferItemsList (technically an Array), from which you will still have to pick the one that holds the .type you want to access.
    In your case you only know it's an image, but there are several types available for images, so you need to determine which one it is while doing this check.

    document.getElementById('btn').onclick = async (evt) => {
      const auth = await navigator.permissions.query( { name: "clipboard-read" } );
      if( auth.state !== 'denied' ) {
        const item_list = await navigator.clipboard.read();
        let image_type; // we will feed this later
        const item = item_list.find( item => // choose the one item holding our image
          item.types.some( type => { // does this item have our type
            if( type.startsWith( 'image/' ) ) {
              image_type = type; // store which kind of image type it is
              return true;
            }
          } )
        );
        const file = item && await item.getType( image_type );
        console.log( file );
      }
    };
    img{ height: 100vh; }
    <button id="btn">read clipboard content</button>
    <figure>
      <figcaption>Copy this image</figcaption>
      <img src="https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png">
    </figure>