


js は、画像を貼り付けてアップロードするための Ctrl+V を実装します (Chrome、Firefox、IE11 と互換性があります)_JavaScript スキル
誰もが多かれ少なかれさまざまなリッチテキストエディタを使用していますが、その中には画像をコピーしてテキストボックスに貼り付けると、画像がアップロードされるので、これは便利です。実装されましたか?
原理分析
抽出操作: copy=>paste=>upload
この操作中に行う必要があるのは、貼り付けイベントをリッスン => クリップボード内のコンテンツを取得 => アップロード要求を送信することだけです。
以下の内容を簡単に理解するには、まずいくつかの点を理解する必要があります:
- アップロードできるのは、Web ページの写真 (Web ページ上の写真を右クリックしてコピー) とスクリーンショット (スクリーンショット ツールで撮影した写真、例: qq スクリーンショット) のみです。貼り付けてアップロードすることはできません。システム内の画像 (コンピュータのデスクトップからハードディスクにコピーされたもの) は、まったく異なる場所に存在します。
- スニッピングツールでキャプチャした画像は、Webページ上で右クリックしてコピーした画像とは若干異なるため、加工方法も異なります。
- 貼り付けイベントに注意してください: 貼り付け (右クリックで貼り付け/ctrl+v) 操作を実行すると、このアクションは「貼り付け」という名前のクリップボード イベントをトリガーします。このイベントは、次の場合にトリガーされます。カッティング ボード上のデータを対象要素の前に挿入します。ターゲット要素 (カーソルがある場所) が編集可能な要素 (例: contenteditable 属性が設定された div。Textarea は機能しません。) の場合、貼り付けアクションにより、クリップボード内のデータがターゲット要素に挿入されます。 ; ターゲット要素が編集できない場合、データは挿入されませんが、貼り付けイベントはトリガーされます。貼り付けプロセス中、データは読み取り専用です。この段落は、w3.org_the-paste-action から翻訳されたものです。
-
残念ながら、テストの結果、chrome (最新バージョン)、firefox (最新バージョン)、ie11 でのペースト イベントの実装が w3c に完全に準拠していないことが判明しました。独自の違いがあります (w3c ペースト標準はドラフト段階にのみあります)。
クロム:
<textarea ></textarea> <div contenteditable style="width: 100px;height: 100px; border:1px solid"> </div> <script> document.addEventListener('paste', function (event) { console.log(event) }) </script>
- event有clipboardData属性,且clipboardData有item属性,clipboardData.item中的元素(对象)有type和kind属性;
- 无论在哪进行粘贴,均可触发paste事件;
- 在div(未特殊声明时,本文div均指设置了contenteditable属性的div) 里粘贴截图,不显示图片。img.src为base64编码字符串;
- 在div里粘贴网页图片,直接显示图片,img.src为图片地址。
firefox:
- event有clipboardData属性,clipboardData没有item属性;
- 只有在textarea里或者可编辑的div(里才粘贴才触发paste事件;
- 在div里粘贴截图,直接显示图片,img.src为base64编码字符串;
- 在div里粘贴网页图片,表现同chrome。
ie11:(不截图了,可自行试验,其他浏览器同理<( ̄▽ ̄)/,因为懒...)
- event没有clipboardData属性;
- 只在可编辑的div中粘贴才触发paste事件;
- 在div里粘贴截图,直接显示图片,img.src为base64编码字符串;
- 在div里粘贴网页图片,表现同chrome。
监听了paste事件,也知道了表现形式,接下来就是如何获取数据了:
chrome有特定的方法,利用clipboardData.items、getAsFile()、new FileReader()等api可以在paste回调函数里获取到剪贴板里图片的base64编码字符串(无论是截图粘贴的还是网页图片复制粘贴的),ie11,firefox没有这样的api,不过依然有办法可以获取,因为数据已经表现在img的src里了,对于截图粘贴的,直接取img的src属性值(base64),对于网页粘贴的,则把地址传给后台,然后根据地址down下来,存在自己的服务器,最后把新地址返回来交给前端展示就ok了。为了保持一致性便于管理,统一将所有情况(截图、网页)中的img的src属性替换为自己存储的地址。因此可以得到以下核心代码(注释很全哦~~):
html展示:
<head> <meta charset="UTF-8"> <title>Document</title> <style> body { display: -webkit-flex; display: flex; -webkit-justify-content: center; justify-content: center; } #tar_box { width: 500px; height: 500px; border: 1px solid red; } </style>
前端js处理逻辑:
document.addEventListener('paste', function (event) { console.log(event) var isChrome = false; if ( event.clipboardData || event.originalEvent ) { //not for ie11 某些chrome版本使用的是event.originalEvent var clipboardData = (event.clipboardData || event.originalEvent.clipboardData); if ( clipboardData.items ) { // for chrome var items = clipboardData.items, len = items.length, blob = null; isChrome = true; //items.length比较有意思,初步判断是根据mime类型来的,即有几种mime类型,长度就是几(待验证) //如果粘贴纯文本,那么len=1,如果粘贴网页图片,len=2, items[0].type = 'text/plain', items[1].type = 'image/*' //如果使用截图工具粘贴图片,len=1, items[0].type = 'image/png' //如果粘贴纯文本+HTML,len=2, items[0].type = 'text/plain', items[1].type = 'text/html' // console.log('len:' + len); // console.log(items[0]); // console.log(items[1]); // console.log( 'items[0] kind:', items[0].kind ); // console.log( 'items[0] MIME type:', items[0].type ); // console.log( 'items[1] kind:', items[1].kind ); // console.log( 'items[1] MIME type:', items[1].type ); //阻止默认行为即不让剪贴板内容在div中显示出来 event.preventDefault(); //在items里找粘贴的image,据上面分析,需要循环 for (var i = 0; i < len; i++) { if (items[i].type.indexOf("image") !== -1) { // console.log(items[i]); // console.log( typeof (items[i])); //getAsFile() 此方法只是living standard firefox ie11 并不支持 blob = items[i].getAsFile(); } } if ( blob !== null ) { var reader = new FileReader(); reader.onload = function (event) { // event.target.result 即为图片的Base64编码字符串 var base64_str = event.target.result //可以在这里写上传逻辑 直接将base64编码的字符串上传(可以尝试传入blob对象,看看后台程序能否解析) uploadImgFromPaste(base64_str, 'paste', isChrome); } reader.readAsDataURL(blob); } } else { //for firefox setTimeout(function () { //设置setTimeout的原因是为了保证图片先插入到div里,然后去获取值 var imgList = document.querySelectorAll('#tar_box img'), len = imgList.length, src_str = '', i; for ( i = 0; i < len; i ++ ) { if ( imgList[i].className !== 'my_img' ) { //如果是截图那么src_str就是base64 如果是复制的其他网页图片那么src_str就是此图片在别人服务器的地址 src_str = imgList[i].src; } } uploadImgFromPaste(src_str, 'paste', isChrome); }, 1); } } else { //for ie11 setTimeout(function () { var imgList = document.querySelectorAll('#tar_box img'), len = imgList.length, src_str = '', i; for ( i = 0; i < len; i ++ ) { if ( imgList[i].className !== 'my_img' ) { src_str = imgList[i].src; } } uploadImgFromPaste(src_str, 'paste', isChrome); }, 1); } }) function uploadImgFromPaste (file, type, isChrome) { var formData = new FormData(); formData.append('image', file); formData.append('submission-type', type); var xhr = new XMLHttpRequest(); xhr.open('POST', '/upload_image_by_paste'); xhr.onload = function () { if ( xhr.readyState === 4 ) { if ( xhr.status === 200 ) { var data = JSON.parse( xhr.responseText ), tarBox = document.getElementById('tar_box'); if ( isChrome ) { var img = document.createElement('img'); img.className = 'my_img'; img.src = data.store_path; tarBox.appendChild(img); } else { var imgList = document.querySelectorAll('#tar_box img'), len = imgList.length, i; for ( i = 0; i < len; i ++) { if ( imgList[i].className !== 'my_img' ) { imgList[i].className = 'my_img'; imgList[i].src = data.store_path; } } } } else { console.log( xhr.statusText ); } }; }; xhr.onerror = function (e) { console.log( xhr.statusText ); } xhr.send(formData); }
用express.js搭的简易后台的接收逻辑:
router.post('/', upload.array(), function (req, res, next) { //1.获取客户端传来的src_str字符串=>判断是base64还是普通地址=>获取图片类型后缀(jpg/png etc) //=>如果是base64替换掉"前缀"("data:image\/png;base64," etc) //2.base64 转为 buffer对象 普通地址则先down下来 //3.写入硬盘(后续可以将地址存入数据库) //4.返回picture地址 var src_str = req.body.image, timestamp = new Date().getTime(); if ( src_str.match(/^data:image\/png;base64,|^data:image\/jpg;base64,|^data:image\/jpg;base64,|^data:image\/bmp;base64,/) ) { //处理截图 src_str为base64字符串 var pic_suffix = src_str.split(';',1)[0].split('/',2)[1], base64 = src_str.replace(/^data:image\/png;base64,|^data:image\/jpg;base64,|^data:image\/jpg;base64,|^data:image\/bmp;base64,/, ''), buf = new Buffer(base64, 'base64'), store_path = 'public/images/test_' + timestamp + '.' + pic_suffix; fs.writeFile(store_path, buf, function (err) { if (err) { throw err; } else { res.json({'store_path': store_path}); } }); } else {// 处理非chrome的网页图片 src_str为图片地址 var temp_array = src_str.split('.'), pic_suffix = temp_array[temp_array.length - 1], store_path = 'public/images/test_' + timestamp + '.' + pic_suffix, wstream = fs.createWriteStream(store_path); request(src_str).pipe(wstream); wstream.on('finish', function (err) { if( err ) { throw err; } else { res.json({"store_path": store_path}); } }); } });
需要node环境:安装node=>npm intall=>node app.js)
以上就是本文的全部内容,希望对大家的学习有所帮助。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











顔の検出および認識テクノロジーは、すでに比較的成熟しており、広く使用されているテクノロジーです。現在、最も広く使用されているインターネット アプリケーション言語は JS ですが、Web フロントエンドでの顔検出と認識の実装には、バックエンドの顔認識と比較して利点と欠点があります。利点としては、ネットワーク インタラクションの削減とリアルタイム認識により、ユーザーの待ち時間が大幅に短縮され、ユーザー エクスペリエンスが向上することが挙げられます。欠点としては、モデル サイズによって制限されるため、精度も制限されることが挙げられます。 js を使用して Web 上に顔検出を実装するにはどうすればよいですか? Web 上で顔認識を実装するには、JavaScript、HTML、CSS、WebRTC など、関連するプログラミング言語とテクノロジに精通している必要があります。同時に、関連するコンピューター ビジョンと人工知能テクノロジーを習得する必要もあります。 Web 側の設計により、次の点に注意してください。

PHP と JS を使用して株のローソク足チャートを作成する方法。株のローソク足チャートは、株式市場で一般的なテクニカル分析グラフィックです。始値、終値、最高値、株価などのデータを描画することで、投資家が株式をより直観的に理解するのに役立ちます。株価の最低価格、価格変動。この記事では、PHP と JS を使用して株価のローソク足チャートを作成する方法を、具体的なコード例とともに説明します。 1. 準備 開始する前に、次の環境を準備する必要があります。 1. PHP を実行するサーバー 2. HTML5 および Canvas をサポートするブラウザー 3

株式分析に必須のツール: PHP および JS でローソク足チャートを描画する手順を学びます。特定のコード例が必要です。インターネットとテクノロジーの急速な発展に伴い、株式取引は多くの投資家にとって重要な方法の 1 つになりました。株価分析は投資家の意思決定の重要な部分であり、ローソク足チャートはテクニカル分析で広く使用されています。 PHP と JS を使用してローソク足チャートを描画する方法を学ぶと、投資家がより適切な意思決定を行うのに役立つ、より直感的な情報が得られます。ローソク足チャートとは、株価をローソク足の形で表示するテクニカルチャートです。株価を示しています

JS と Baidu Map を使用してマップ パン機能を実装する方法 Baidu Map は広く使用されている地図サービス プラットフォームで、Web 開発で地理情報、位置情報、その他の機能を表示するためによく使用されます。この記事では、JS と Baidu Map API を使用してマップ パン機能を実装する方法と、具体的なコード例を紹介します。 1. 準備 Baidu Map API を使用する前に、Baidu Map Open Platform (http://lbsyun.baidu.com/) で開発者アカウントを申請し、アプリケーションを作成する必要があります。作成完了

JS と Baidu Maps を使用してマップ クリック イベント処理を実装する方法の概要: Web 開発では、地理的位置と地理情報を表示するためにマップ関数を使用することが必要になることがよくあります。マップ上のクリック イベント処理は、マップ機能の一般的に使用される重要な部分です。この記事では、JS と Baidu Map API を使用して地図のクリック イベント処理機能を実装する方法と、具体的なコード例を紹介します。手順: Baidu Map の API ファイルをインポートします。まず、Baidu Map API のファイルを HTML ファイルにインポートします。これは、次のコードによって実現できます。

JS と Baidu Maps を使用してマップ ヒート マップ機能を実装する方法 はじめに: インターネットとモバイル デバイスの急速な発展に伴い、マップは一般的なアプリケーション シナリオになりました。視覚的な表示方法として、ヒート マップはデータの分布をより直観的に理解するのに役立ちます。この記事では、JS と Baidu Map API を使用してマップ ヒート マップ機能を実装する方法と、具体的なコード例を紹介します。準備作業: 開始する前に、次の項目を準備する必要があります: Baidu 開発者アカウント、アプリケーションの作成、対応する AP の取得

インターネット金融の急速な発展に伴い、株式投資を選択する人がますます増えています。株式取引では、ローソク足チャートは一般的に使用されるテクニカル分析手法であり、株価の変化傾向を示し、投資家がより正確な意思決定を行うのに役立ちます。この記事では、PHP と JS の開発スキルを紹介し、株価ローソク足チャートの描画方法を読者に理解してもらい、具体的なコード例を示します。 1. 株のローソク足チャートを理解する 株のローソク足チャートの描き方を紹介する前に、まずローソク足チャートとは何かを理解する必要があります。ローソク足チャートは日本人が開発した

js と vue の関係: 1. Web 開発の基礎としての JS、2. フロントエンド フレームワークとしての Vue.js の台頭、3. JS と Vue の補完関係、4. JS と Vue の実用化ビュー。
