zoukankan      html  css  js  c++  java
  • div中粘贴图片并上传服务器 div中拖拽图片文件并上传服务器

    应用简介:此文主要是描述如何在前端div中直接ctrl+v 粘贴图片,并上传到服务器,包括拖拽图片文件到div中

    应用场景描述:用QQ或者其它切图软件截图,在指定的div中ctrl+v 粘贴并显示,点击上传按钮,图片上传到服务器。类似实现了此功能的网站有 知乎 强力建议博客园实现此功能,写博客时插入图片方便的多。

    适用环境:本代码目前适用谷歌浏览器、火狐,其它浏览器需要稍微改良一下即可,问题不大。

    开发环境:vs2015 mvc 

    不说废话了,开始吧:

     1:首先创建HTML元素,我们要粘贴的图片就是显示在 id=pasteImg 的div里面,注意 需要设置div的 contenteditable="true" 属性才可以编辑哦。

    <div id="pasteImg" style="400px;height:300px;border:dashed" contenteditable="true"></div>
    <button style="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上传图片数据

        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后台,根据自己的语言不通采用对应的处理方式

    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);
        }
  • 相关阅读:
    kafka-python基本使用
    RabbitMq 消息队列详解
    Socket 编程
    python 进程, 线程 ,协程,锁,协程应用到爬虫的讲解
    python中with的用法
    为什么 Elasticsearch 需要堆内存来存储数据
    面向数据的架构
    跟我一起学Redis之看完这篇比常人多会三种类型实战(又搞了几个小时)
    跟我一起学.NetCore之熟悉的接口权限验证不能少(Jwt)
    跟我一起学.NetCore之WebApi接口裸奔有风险(Jwt)
  • 原文地址:https://www.cnblogs.com/fj99/p/5499233.html
Copyright © 2011-2022 走看看