應用簡介:此文主要是描述如何在前端div中直接ctrl+v 粘貼圖片,並上傳到服務器,包括拖拽圖片文件到div中html
應用場景描述:用QQ或者其它切圖軟件截圖,在指定的div中ctrl+v 粘貼並顯示,點擊上傳按鈕,圖片上傳到服務器。相似實現了此功能的網站有 知乎 強力建議博客園實現此功能,寫博客時插入圖片方便的多。前端
適用環境:本代碼目前適用谷歌瀏覽器、火狐,其它瀏覽器須要稍微改良一下便可,問題不大。node
開發環境:vs2015 mvc web
不說廢話了,開始吧:ajax
1:首先建立HTML元素,咱們要粘貼的圖片就是顯示在 id=pasteImg 的div裏面,注意 須要設置div的 contenteditable="true" 屬性才能夠編輯哦。瀏覽器
<div id="pasteImg" style="width:400px;height:300px;border:dashed" contenteditable="true"></div> <button style="width:30px;height:20px;" id="btnGO">上傳圖片</button>
2:寫js代碼:綁定粘貼事件 上傳圖片服務器服務器
window.onload = function () { function paste_img(e) { if (e.clipboardData && e.clipboardData.items) { var imageContent = e.clipboardData.getData('image/png'); ele = e.clipboardData.items for (var i = 0; i < ele.length; ++i) {
//粘貼圖片 if (ele[i].kind == 'file' && ele[i].type.indexOf('image/') !== -1) { var blob = ele[i].getAsFile(); window.URL = window.URL || window.webkitURL; var blobUrl = window.URL.createObjectURL(blob); // 顯示到div中,此時是顯示的本地圖片數據,並無上傳到服務器 var new_img = document.createElement('img'); new_img.setAttribute('src', blobUrl); new_img.setAttribute('blobdata', blob);
// 移動div光標到新元素後面 insertHtmlAtCaret(new_img);
// 直接上傳,固然你也能夠不在這上傳,能夠點擊按鈕在上傳
uploadImg(blob); }
//粘貼文本 else if (ele[i].kind === "string" && ele[i].type.indexOf('text/plain') != -1) {
//粘貼文本回調函數
ele[i].getAsString(
function (str) { insertHtmlAtCaret(document.createTextNode(str));//插入文本到光標處 並移動光標到新位置 }) } else return; } } else { alert('不支持的瀏覽器'); } }
//綁定粘貼事件 document.getElementById('pasteImg').onpaste = function () { paste_img(event); return false; };
}
3:下面是insertHtmlAtCaret方法,主要實如今div移動光標的位置,用不上的直接跳過此步驟併發
//聊天內容框 插入文本或者其餘元素後,移動置光標到最新處 function insertHtmlAtCaret(childElement) { var sel, range; if (window.getSelection) { // IE9 and non-IE sel = window.getSelection(); if (sel.getRangeAt && sel.rangeCount) { range = sel.getRangeAt(0); range.deleteContents(); var el = document.createElement("div"); el.appendChild(childElement); var frag = document.createDocumentFragment(), node, lastNode; while ((node = el.firstChild)) { lastNode = frag.appendChild(node); } range.insertNode(frag); if (lastNode) { range = range.cloneRange(); range.setStartAfter(lastNode); range.collapse(true); sel.removeAllRanges(); sel.addRange(range); } } } else if (document.selection && document.selection.type != "Control") { // IE < 9 //document.selection.createRange().pasteHTML(html); } }
4:採用XHR上傳圖片數據mvc
var createStandardXHR = function () { try { return new window.XMLHttpRequest(); } catch (e) { return false; } }; var createActiveXHR = function () { try { return new window.ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { return false; } }; var xhr; function createXHR() { var temp = createStandardXHR() || createActiveXHR(); if (window.XDomainRequest === undefined) { return temp; } else { return new XDomainRequest(); } } //前端上傳方法 function uploadImg(obj) { xhr = createXHR(); if (xhr) { xhr.onerror = err; xhr.ontimeout = timeo; xhr.onprogress = progres; xhr.onload = loadd; xhr.timeout = timeo; } else { alert("Failed to create"); } //發送的數據 var fd = new FormData(); fd.append("image", obj, "imgtest.png"); //使用ajax發送 xhr.open('POST', '/Home/uploadFun', true);//第二個參數是服務器處理action,各個語言提供方式不同,我這是.net mvc 後臺處理的,具體方法見步驟5 xhr.send(fd); } function err() { // alert("XDR onerror"); } function timeo() { // alert("XDR ontimeout"); } function loadd() { // alert("上傳完成"); // alert("Got: " + xhr.responseText); } function progres() { //alert("XDR onprogress"); } function stopdata() { xhr.abort(); }
5:後臺接收圖片數據處理方法,本人採用 .net MVC後臺,根據本身的語言不通採用對應的處理方式app
public class HomeController : Controller { public ActionResult Index() { return View(); } [HttpPost] public ActionResult uploadFun() { if (Request.Files.Count > 0) { var file = Request.Files[0]; if (file != null && file.ContentLength > 0) { //驗證文件格式 var extension = Path.GetExtension(file.FileName); //if (extension != ".xls" && extension != ".xlsx") //{ //}
//上傳成功的圖片URL var fileFullPath = Path.Combine(Request.MapPath("~/uploads"), DateTime.Now.ToString("yyyyMMddHHmmss") + Path.GetFileName(file.FileName)); file.SaveAs(fileFullPath); return Content("上傳成功!url:"+fileFullPath , "text/plain");
}
}
returnnew JsonResult();
}
}
6:擴展一下,拖拽圖片文件到div 直接發送
//如下是拖拽事件 document.addEventListener("dragenter", function (e) { e.stopPropagation(); e.preventDefault(); }, false); document.addEventListener("dragleave", function (e) { e.stopPropagation(); e.preventDefault(); }, false); document.addEventListener("dragover", function (e) { e.stopPropagation(); e.preventDefault(); }, false); document.addEventListener("drop", function (e) { e.stopPropagation(); e.preventDefault(); handleFiles(e.dataTransfer.files); }, false); //拖拽文件處理事件 handleFiles = function (files) { for (var i = 0; i < files.length; i++) { var file = files[i]; //若是拖住進來的是圖片文件則顯示 if (file.type.match(/image*/)) { $("#pasteImg").focus();
var blob =file;
window.URL = window.URL || window.webkitURL;
var blobUrl = window.URL.createObjectURL(blob); // 顯示到div中,此時是顯示的本地圖片數據,並無上傳到服務器
var new_img = document.createElement('img');
new_img.setAttribute('src', blobUrl);
new_img.setAttribute('blobdata', blob);
// 移動div光標到新元素後面 insertHtmlAtCaret(new_img);
// 直接上傳,固然你也能夠不在這上傳,能夠點擊按鈕在上傳
uploadImg(blob);
} else { continue; } } }
7:至此就實現了ctrl+v 粘貼圖片併發送服務器,也具備拖拽圖片文件 併發送服務器的功能
發散:能夠作文件上傳的東西
待解決:IE瀏覽器和火狐瀏覽器能夠直接粘貼圖片及文件,顯示的是數據而不是blob格式而已
這是隔日再來寫的,如下是火狐瀏覽器解決方法,已親測,可行,只不過,火狐不要寫粘貼事件,它已自帶
document.getElementById('btnGO').onclick = function () { var img = $("#pasteImg").find('img').eq(0); var blob = dataURLtoBlob(img.attr('src')); //上傳方法 uploadImg(blob); }; //**dataURL to blob** function dataURLtoBlob(dataurl) { var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime }); } //**blob to dataURL** function blobToDataURL(blob, callback) { var a = new FileReader(); a.onload = function (e) { callback(e.target.result); } a.readAsDataURL(blob); }