Passer au contenu principal




Accès au presse-papiers plus sécurisé et déverrouillé pour le texte et les images


Mise à jour

Ces dernières années, les navigateurs ont utilisé
document.execCommand ()

para interacciones con el portapapeles. Aún cuando es ampliamente compatible, este método de cortar y pegar tenía un costo: el acceso al portapapeles era sincrónico y solo podía leer y escribir en el DOM.

Eso está bien para pequeños fragmentos de texto, pero hay muchos casos en los que bloquear la página para la transferencia del portapapeles es una mala experiencia. Es viable que se necesite una desinfección o decodificación de imágenes que requiera mucho tiempo antes de que el contenido se pueda pegar de forma segura. Es viable que el navegador necesite cargar o incorporar recursos vinculados desde un documento pegado. Eso bloquearía la página mientras espera en el disco o la red. Imagine agregar permisos a la mezcla, requiriendo que el navegador bloquee la página mientras solicita acceso al portapapeles. A la vez, los permisos establecidos alrededor
document.execCommand () pour l'interaction avec le presse-papiers sont définis de manière lâche et varient d'un navigateur à l'autre.

Les
API du Presse-papiers Async
résout ces problèmes en fournissant un modèle d'autorisations bien défini qui ne verrouille pas la page. Safari récemment annoncé prise en charge dans la version 13.1. Con eso, los principales navegadores disponen un nivel básico de soporte. A la hora de escribir estas líneas, Firefox solo admite texto; y el soporte de imágenes está limitado a PNG en algunos navegadores. Si está interesado en usar la API,
consulter un tableau de support du navigateur
avant de continuer.

Este post explica cómo escribir texto e imágenes y cómo leerlos desde el portapapeles. Este post no cubre Politique de fonctionnalité pour le presse-papiers qui a atterri sur Chrome 85.

La API Async Clipboard se limita a manejar texto e imágenes. Chrome 84 introduce una función experimental que posibilita que el portapapeles maneje cualquier tipo de datos arbitrario.

Copier: écrire des données dans le presse-papiers

writeText ()

Pour copier du texte dans la légende du presse-papiers writeText (). Puesto que esta API es asincrónica, la writeText () La fonction renvoie une promesse qui est résolue ou rejetée selon que le texte passé est copié correctement:

fonction asynchrone copyPageUrl ( ) {
essayez {
attendre le navigateur . presse-papiers . writeText ( location . href ) ;
console . log ( 'URL de la page copiée dans le presse-papiers' ) ;
} catch ( err ) {
console . error ( 'Failed to copy:' , err ) ;
}
}

Écrire()

Vraiment, writeText () c'est juste une méthode pratique pour le générique écrivez ()
método, que además le posibilita copiar imágenes al portapapeles. Me gusta writeText (), est asynchrone et renvoie une promesse.

Para escribir una imagen en el portapapeles, requiere la imagen como
goutte. Una forma de hacer esto es solicitando la imagen de un servidor utilizando aller chercher (), después llamando
blob () en la solución.

Solicitar una imagen del servidor puede no ser deseable o viable por una gama de razones. Por suerte, además puede dibujar la imagen en un lienzo y llamar al lienzo ‘
toBlob ()

méthode.

Passez ensuite un tableau de Presse-papiers objets en tant que paramètre pour le écrivez ()
método. Hoy en día, solo puede pasar una imagen al mismo tiempo, pero esperamos agregar soporte para diversos imágenes en el futuro. Presse-papiers prend un objet avec le type MIME de l'image comme clé et le blob comme valeur. Pour les objets Blob obtenus à partir de aller chercher () ou canvas.toBlob (), les blob.type La propiedad contiene de forma automática el tipo MIME correcto para una imagen.

essayez {
const imgURL = '/images/generic/file.png' ;
const data = attendre la récupération ( imgURL ) ;
const blob = attendre les données . blob ( ) ;
attendre le navigateur . presse-papiers . écrire ( [
nouveau ClipboardItem ( {
[ blob . type ] : blob
} )
] ) ;
console . log ( 'Image copiée.' ) ;
} catch ( err ) {
console . erreur (. err nom, err message.);
}

L'événement de copie

Dans le cas où un utilisateur lance une copie du presse-papiers, des données non textuelles lui seront fournies sous forme de blob. Les
copie un événement
comprend un presse-papiers con los ítems que ya están en el formato correcto, eliminando la necesidad de crear manualmente un Blob. Llamada preventDefault () para evitar el comportamiento predeterminado a favor de su propia lógica, después copie el contenido en el portapapeles. Lo que no se cubre en este ejemplo es cómo recurrir a API anteriores cuando la API del Portapapeles no es compatible. Cubriré eso en Detección de características, más adelante en este post.

document . addEventListener ( 'copie' , async ( e ) => {
e . preventDefault ( ) ;
essayez {
laissez clipboardItems = [ ] ;
for ( élément const de e . clipboardData . éléments ) {
if ( ! item . type . startsWith ( 'image /' ) ) {
continuer ;
}
clipboardItems . pousser (
nouveau ClipboardItem ( {
[ élément . type ] : élément ,
} )
) ;
attendre le navigateur . presse-papiers . écrire ( clipboardItems ) ;
console . log ( 'Image copiée.' ) ;
}
} catch ( err ) {
console . erreur (. err nom, err message.);
}
} ) ;

Coller: lire les données du presse-papiers

Lisez le texte ()

Pour lire le texte du presse-papiers, appelez navigator.clipboard.readText () et attendez que la promesse retournée soit résolue:

fonction asynchrone getClipboardContents ( ) {
essayez {
const text = attendre le navigateur . presse-papiers . readText ( ) ;
console . log ( 'Contenu collé:' , texte ) ;
} catch ( err ) {
console . error ( 'Impossible de lire le contenu du presse-papiers:' , err ) ;
}
}

lis()

Les navigator.clipboard.read () El método además es asincrónico y devuelve una Promesa. Para leer una imagen del portapapeles, obtenga una lista de
Presse-papiers

objetos, después iterar sobre ellos.

Chaque Presse-papiers puede contener su contenido en diferentes tipos, por lo que deberá iterar sobre el listado de tipos, nuevamente utilizando un pour ... de lien. Pour chaque type, appelez getType () con el tipo actual como argumento para conseguir el Blob respectivo. Como antes, este código no está vinculado a imágenes y funcionará con otros tipos de archivos futuros.

fonction asynchrone getClipboardContents ( ) {
essayez {
const clipboardItems = attendre le navigateur . presse-papiers . lire ( ) ;
for ( const clipboardItem of clipboardItems ) {
for ( type const de clipboardItem . types ) {
const blob = attendre clipboardItem . getType ( type ) ;
console . log ( URL . createObjectURL ( blob ) ) ;
}
}
} catch ( err ) {
console . erreur (. err nom, err message.);
}
}

L'événement coller

Como se señaló previamente, hay planes para introducir eventos para que funcionen con la API del Portapapeles, pero por ahora puede utilizar el existente pâte un événement. Fonctionne très bien avec les nouvelles méthodes asynchrones pour lire le texte du presse-papiers. Comme avec le copie événement, n'oubliez pas d'appeler preventDefault ().

document . addEventListener ( 'coller' , async ( e ) => {
e . preventDefault ( ) ;
const text = attendre le navigateur . presse-papiers . readText ( ) ;
console . log ( 'Texte collé:' , texte ) ;
} ) ;

Comme avec le copie événement, revenir à des API plus anciennes lorsque l'API du Presse-papiers n'est pas prise en charge sera traité dans la détection de fonction.

Manejo de diversos tipos de archivos

La mayoría de las implementaciones colocan diversos formatos de datos en el portapapeles para una sola operación de corte o copia. Hay dos razones para ello: como desarrollador de aplicaciones, no tiene forma de conocer las capacidades de la aplicación en la que un usuario desea copiar texto o imágenes, y muchas aplicaciones admiten pegar datos estructurados como texto sin formato. Esto se presenta a los usuarios con un Éditer élément de menu avec un nom comme Coller et assortir le style ou Coller sans mise en forme.

El siguiente ejemplo muestra cómo hacer esto. Este ejemplo utiliza aller chercher () para conseguir datos de imagen, pero además podría provenir de un

ou l'API du système de fichiers natif.

copie de fonction ( ) {
image const = attendre fetch ( 'kitten.png' ) ;
const text = new Blob ( [ 'Cute kitten endormi' ] , { type : 'text / plain' } ) ;
const item = new ClipboardItem ( {
'text / plain' : texte ,
'image / png' : image
} ) ;
attendre le navigateur . presse-papiers . écrire ( [ élément ] ) ;
}

Sécurité et autorisations

El acceso al portapapeles siempre ha supuesto un obstáculo de seguridad para los navegadores. Sin los permisos adecuados, una página podría copiar silenciosamente todo tipo de contenido malicioso en el portapapeles de un usuario que produciría resultados catastróficos al pegarlo. Imagina una página web que copia silenciosamente rm -rf / ou un
image de la pompe de décompression
dans votre presse-papiers.

prompt-5760362

La demande d'autorisation pour l'API Clipboard.

Dar a las páginas web acceso de lectura sin restricciones al portapapeles es todavía más problemático. Los usuarios copian rutinariamente información confidencial como contraseñas y datos personales al portapapeles, que después puede ser leído por cualquier página sin el conocimiento del usuario.

Como ocurre con muchas API nuevas, la API del Portapapeles solo es compatible con las páginas publicadas mediante HTTPS. Para ayudar a prevenir el abuso, el acceso al portapapeles solo está permitido cuando una página es la pestaña activa. Las páginas en pestañas activas pueden escribir en el portapapeles sin solicitar permiso, pero leer desde el portapapeles siempre necesita permiso.

Se han incorporado permisos para copiar y pegar al
API des autorisations. Les presse-papiers el permiso se otorga de forma automática a las páginas cuando son la pestaña activa. los presse-papiers Une autorisation doit être demandée, ce que vous pouvez faire en essayant de lire les données du presse-papiers. Le code suivant montre le dernier:

const queryOpts = { nom : 'clipboard-read' , allowWithoutGesture : false } ;
const permissionStatus = attendre le navigateur . autorisations . requête ( queryOpts ) ;
console . log ( permissionStatus . state ) ;


permissionStatus . onchange = ( ) => {
console . log ( permissionStatus . state ) ;
} ;

Además puede controlar si se necesita un gesto de usuario para invocar cortar o pegar utilizando el allowWithoutGesture opción. El valor predeterminado de este valor varía según el navegador, por lo que siempre debe incorporarlo.

Aquí es donde la naturaleza asincrónica de la API del Portapapeles es verdaderamente útil: intentar leer o escribir datos del portapapeles de forma automática solicita al usuario permiso si todavía no se ha otorgado. Puesto que la API se basa en promesas, esto es totalmente transparente, y un usuario que niega el permiso del portapapeles hace que la promesa se rechace para que la página pueda responder adecuadamente.

Porque Chrome solo posibilita el acceso al portapapeles cuando una página es la pestaña activa, encontrará que algunos de los ejemplos aquí no se ejecutan si se pegan de forma directa en DevTools, puesto que DevTools en sí es la pestaña activa. Hay un truco: diferir el acceso al portapapeles utilizando setTimeout (), después haga clic rápidamente dentro de la página para enfocarla antes de llamar a las funciones:

setTimeout ( async ( ) => {
const text = attendre le navigateur . presse-papiers . readText ( ) ;
console . log ( texte ) ;
} , 2000 ) ;

Détection des fonctionnalités

Para utilizar la API Async Clipboard mientras es compatible con todos los navegadores, pruebe
navigator.clipboard y recurrir a métodos anteriores. A modo de ejemplo, así es como puede poner en práctica el pegado para incluir otros navegadores.

document . addEventListener ( 'coller' , async ( e ) => {
e . preventDefault ( ) ;
laissez le texte ;
if ( navigateur . presse-papiers ) {
text = attendre le navigateur . presse-papiers . readText ( ) ;
}
else {
texte = e . clipboardData . getData ( 'text / plain' ) ;
}
console . log ( 'Texte collé:' , texte ) ;
} ) ;

Esa no es toda la historia. Antes de la API Async Clipboard, existía una combinación de diferentes implementaciones de copiar y pegar en los navegadores web. En la mayoría de los navegadores, la función de copiar y pegar del navegador se puede activar a través de
document.execCommand ('copie') y document.execCommand ('coller'). Si le texte à copier est une chaîne qui n'est pas présente dans le DOM, il doit être injecté dans le DOM et sélectionné:

bouton . addEventListener ( 'clic' , ( e ) => {
const entrée = document . createElement ( 'entrée' ) ;
document . corps . appendChild ( entrée ) ;
entrée . valeur = texte ;
entrée . focus ( ) ;
entrée . sélectionnez ( ) ;
résultat const = document . execCommand ( 'copier' ) ;
if ( result === 'échec' ) {
console . error ( 'Impossible de copier le texte.' ) ;
}
} ) ;

En Internet Explorer, además puede entrar al portapapeles mediante
window.clipboardData. En cas d'accès dans le cadre d'un geste de l'utilisateur, tel qu'un événement de clic, qui fait partie d'une demande d'autorisation responsable, aucun message d'autorisation ne s'affiche.

Ville

Puede jugar con la API Async Clipboard en las demostraciones a continuación. Podrías obtener un
NotAllowedError si se ejecuta en un iframe, eso es provocado por el recién implementado
presse-papiers Politique de fonction. Para este caso, ejecute la demostración. de forma directa en Glitch.

Le premier exemple montre comment déplacer du texte sur et en dehors du presse-papiers.

Pour tester l'API avec des images, utilisez cette démo. N'oubliez pas que seuls les PNG sont pris en charge et uniquement dans
[quelques navigateurs] (https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API.

Les prochaines étapes

Chrome travaille activement à étendre l'API du Presse-papiers asynchrone avec des événements simplifiés alignés sur le
Faites glisser et déposez l'API. Debido a los riesgos potenciales, Chrome está pisando con cuidado. Para mantenerse actualizado sobre el progreso de Chrome, mire este post y nuestro blog para conseguir actualizaciones.

Por ahora, la compatibilidad con la API del portapapeles se encuentra disponible en
divers navigateurs.

Bonne copie et collage!

Merci

L'API du Presse-papiers asynchrone a été implémentée par Darwin Huang y Gary Kačmarčík. Darwin además proporcionó la demostración. Gracias a Kyarik y nuevamente a Gary Kačmarčík por revisar partes de este post.

Image de héros de Markus Winkler au
Unsplash.

R Marketing Numérique