• Laravel项目中使用markdown编辑器及图片粘贴上传七牛云


    本文为转载,原文:Laravel项目中使用markdown编辑器及图片粘贴上传七牛云

    Markdown

    Markdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式。
    本次我们选用的编辑器是: Editor.md,官网中也有很详细的介绍。从官网中下载安装

    下载的内容中,也有很多demo可以借鉴。
    在下载的包中,去除一些多余的内容,只保留我们需要的内容,然后加到项目的public目录下,如下图红色框内的内容:

    项目中使用

    在项目中使用editor.md编辑内容时,首先要先在blade模板中添加相对应的引用,css的引用如下:

    <link rel="stylesheet" href="{{asset('editormd/editormd.min.css')}}">

    js的引用如下:

    <script src="{{asset('editormd/editormd.min.js')}}" type="text/javascript"></script>

    然后在html中添加以下代码,作为编辑器区域。

    <div id="myeditormd">
        <textarea style="display:none;"></textarea>
    </div>
    

      

    最后在添加js代码,加载出editor.md:

    <script type="text/javascript">
            var testEditor;
            $(function () {
                testEditor = editormd("myeditormd",{
                    "100%",
                    height:600,
                    syncScrolling:"single",
                    taskList : true,
                    tocm: true,
                    path:"{{asset('/editormd/lib/')}}" + "/",
                    tex:true,
                    flowChart       : true,
                    sequenceDiagram:true,
                    saveHTMLToTextarea : true,
                    imageUploadURL: "php/upload.php",
                });
            });
    </script>
    

      

    相关参数含义:

    saveHTMLToTextarea: 保存 HTML 到 Textarea
    tex: 科学公式TeX语言支持,默认关闭
    flowChart: 流程图支持,默认关闭
    sequenceDiagram: 时序/序列图支持,默认关闭
    toolbar: 工具栏,默认开启
    watch: 实时预览,默认开启

    如此,便可完整的加载出编辑器了。效果如下图:

    其中还有些比较重要的js方法。

    testEditor.gotoLine(90);//跳转至第90行
    testEditor.show();//显示编辑器
    testEditor.hide;//隐藏编辑器
    testEditor.getMarkdown();//获取markdown代码
    testEditor.getHTML();//获取markdown解析后的html代码
    testEditor.watch();//开启实时预览
    testEditor.unwatch();//关闭实时预览
    testEditor.previewing();//预览
    testEditor.fullscreen();//全屏
    testEditor.showToolbar();//显示工具栏
    testEditor.hideToolbar();//隐藏工具栏

    在编辑器中编辑完内容后,一般情况下,保存的是markdown标记。但是如何解析已保存的markdown标记呢。

    markdown解析

    添加以下引用:

    //css引用
    <link rel="stylesheet" href="{{asset('editormd/editormd.min.css')}}">
    //js引用
    <script src="{{asset('editormd/editormd.min.js')}}" type="text/javascript"></script>
    <script src="{{asset('editormd/lib/marked.min.js')}}"></script>
    <script src="{{asset('editormd/lib/prettify.min.js')}}"></script>
    <script src="{{asset('editormd/lib/raphael.min.js')}}"></script>
    <script src="{{asset('editormd/lib/underscore.min.js')}}"></script>
    <script src="{{asset('editormd/lib/sequence-diagram.min.js')}}"></script>
    <script src="{{asset('editormd/lib/flowchart.min.js')}}"></script>
    <script src="{{asset('editormd/lib/jquery.flowchart.min.js')}}"></script>

    然后在html中添加解析的区域

    <div id="show_editor">
        <textarea style="display: none">{{$article->content}}</textarea>
    </div>

    其中{{$article->content}}为数据库中读取的已保存的markdown标记。
    最后再添加响应的js代码,便可完美解析了。

    <script type="text/javascript">
        $(function() {
            var testEditormdView;
            testEditormdView = editormd.markdownToHTML("show_editor", {
                htmlDecode      : "style,script,iframe",  // you can filter tags decode
                emoji           : true,
                taskList        : true,
                tex             : true,  // 默认不解析
                flowChart       : true,  // 默认不解析
                sequenceDiagram : true,  // 默认不解析
            });
        });
    </script>

    解析后的效果如下图:

    图片粘贴上传

    首先分析一下实现步骤:

    1. QQ截图后在编辑器中粘贴,肯定会有一个粘贴事件,即 paste 事件
    2. 在事件回调函数中对前端进行图片的一次压缩
    3. 前端压缩多是使用canvas,返回的是base64,这里我使用了一个 localResizeIMG.js的插件
    4. 将生成好的base64传给后台,后台可以进行图片的第二次压缩,但是感觉没必要
    5. 后台先得到七牛云的upToken,即一个上传的凭证,然后执行七牛sdk提供的上传函数

      paste事件

      截图之后,在富文本编辑器中右键黏贴或者CTRL V就会触发这个事件,这个事件有一个clipboardData属性。我们需要使用js代码监听paste事件,并获取clipboardData属性,代码如下:

      1. function paste(event) {
                 var clipboardData = event.clipboardData;
                 var items, item, types;
                 if (clipboardData) {
                     items = clipboardData.items;
                     if (!items) {
                         return;
                     }
                     // 保存在剪贴板中的数据类型
                     types = clipboardData.types || [];
                     for (var i = 0; i < types.length; i++) {
                         if (types[i] === 'Files') {
                             item = items[i];
                             break;
                         }
                     }
                     // 判断是否为图片数据
                     if (item && item.kind === 'file' && item.type.match(/^image//i)) {
                         // 读取该图片
                         var file = item.getAsFile(),
                                 reader = new FileReader();
                         reader.readAsDataURL(file);
                         reader.onload = function () {
                             //前端压缩
                             lrz(reader.result, { 1080}).then(function (res) {
                                 $.ajax({
                                     url: "{{asset('php-sdk/myapis/uploadImageToQiliu.php')}}",
                                     type: 'post',
                                     data: {
                                         "image": res.base64,
                                         "name": new Date().getTime() + ".png"
                                     },
                                     contentType: 'application/x-www-form-urlencoded;charest=UTF-8',
                                     success: function (data) {
                                         var imageName;
                                         try {
                                             imageName = JSON.parse(data).key;
                                         } catch (e) {
                                             alert(e.toString);
                                         }
                                         var qiniuUrl = '![](http://opgmvuzyu.bkt.clouddn.com/' + imageName + ')';
                                         testEditor.insertValue(qiniuUrl);
                                     }
                                 })
                             });
                         }
                     }
                 }
             }
             document.addEventListener('paste', function (event) {
                 paste(event);
             })
        

          


      前端压缩

      前端压缩使用的是localResizeIMG.js插件。
      兼容IE10以上,所以还得做个IE版本判断,然后看自己是否需要使用干这个插件,我这里就不写IE的判断了。
      使用方法也很简单,lrz方法接受一个文件路径或者base64的图片,可以设置一个压缩宽度的对象,低于这个宽度的图片不会压缩,大于这个宽度的就会压缩,然后在then方法中取得压缩后的图片:
      得先引入这个插件,可以使用src引入,也支持amd or cmd模块化

      1. <script src="{{asset('js/lrz.bundle.js')}}" type="text/javascript"></script>

      开始使用:

      1. //image就是经过paste事件后得到的图片
        lrz(image, { 1080}).then(function (res) {
         var base64 = res.base64;
        }

      七牛云sdk

      七牛云注册好像就送10G的云储存,需要的可以去注册,先下载七牛云sdk,我使用的是php,地址https://developer.qiniu.com/kodo/sdk/php
      配置这个上传的文件也很简单。将下载后的压缩包解压,删掉一下没用的文件,然后拖到项目中:

      uploadImageToQiliu.php文件是自己新增的,代码如下:

      1. <?php
        require_once __DIR__ . '/../autoload.php';
        use QiniuAuth;
        // 引入上传类
        use QiniuStorageUploadManager;
        $accessKey = '你的accessKey';
        $secretKey = '你的secretKey';
        // 初始化签权对象。
        $auth = new Auth($accessKey, $secretKey);
        $bucket = "空间名字";
        $upToken = $auth->uploadToken($bucket);
        // 初始化 UploadManager 对象并进行文件的上传。
        $uploadMgr = new UploadManager();
        $key = $_POST['name'];
        $filePath = $_POST['image'];
        list($ret, $err) = $uploadMgr->putFile($upToken, $key, $filePath);
        if ($err !== null) {
         echo json_encode($err);
        } else {
         echo json_encode($ret);
        }

      accessKey和secretKey注册后就可以看到,bucket是云储存空间名字。
      接下来是前台传图片和图片名给后台,图片名我就直接用 new Date().getTime() 了。

      1. $.ajax({
         url: "{{asset('php-sdk/myapis/uploadImageToQiliu.php')}}",
         type: 'post',
         data: {
             "image": res.base64,
             "name": new Date().getTime() + ".png"
         },
         contentType: 'application/x-www-form-urlencoded;charest=UTF-8',
         success: function (data) {
             var imageName;
             try {
                 imageName = JSON.parse(data).key;
             } catch (e) {
                 alert(e.toString);
             }
             var qiniuUrl = '![](http://opgmvuzyu.bkt.clouddn.com/' + imageName + ')';
            testEditor.insertValue(qiniuUrl);
         }
        })

      testEditor 是我使用的markdown编辑器的对象实例,testEditor.insertValue(qiniuUrl);就是把格式化好的markdown语句插到光标处。
      整个前端代码如下:

      1. <script type="text/javascript">
             function paste(event) {
                 var clipboardData = event.clipboardData;
                 var items, item, types;
                 if (clipboardData) {
                     items = clipboardData.items;
                     if (!items) {
                         return;
                     }
                     // 保存在剪贴板中的数据类型
                     types = clipboardData.types || [];
                     for (var i = 0; i < types.length; i++) {
                         if (types[i] === 'Files') {
                             item = items[i];
                             break;
                         }
                     }
                     // 判断是否为图片数据
                     if (item && item.kind === 'file' && item.type.match(/^image//i)) {
                         // 读取该图片
                         var file = item.getAsFile(),
                                 reader = new FileReader();
                         reader.readAsDataURL(file);
                         reader.onload = function () {
                             //前端压缩
                             lrz(reader.result, { 1080}).then(function (res) {
                                 $.ajax({
                                     url: "{{asset('php-sdk/myapis/uploadImageToQiliu.php')}}",
                                     type: 'post',
                                     data: {
                                         "image": res.base64,
                                         "name": new Date().getTime() + ".png"
                                     },
                                     contentType: 'application/x-www-form-urlencoded;charest=UTF-8',
                                     success: function (data) {
                                         var imageName;
                                         try {
                                             imageName = JSON.parse(data).key;
                                         } catch (e) {
                                             alert(e.toString);
                                         }
                                         var qiniuUrl = '![](http://opgmvuzyu.bkt.clouddn.com/' + imageName + ')';
                                         testEditor.insertValue(qiniuUrl);
                                     }
                                 })
                             });
                         }
                     }
                 }
             }
             document.addEventListener('paste', function (event) {
                 paste(event);
             })
         </script>

      再编辑器中粘贴完图片的效果如下:

  • 相关阅读:
    C#域名解析
    【转】正则基础之——贪婪与非贪婪模式
    【转】正则基础之——神奇的转义
    总结:实例化SqlParameter时,如果是字符型,一定要指定size属性,还有制定具体的类型
    从数据库里随机读取几条数据
    Html异步下载分析
    C#生成验证码程序
    【转】正则应用之——逆序环视探索
    如何用class在Dictionary里面作为Key使用
    【转】SqlDataReader 提前终止的性能问题
  • 原文地址:https://www.cnblogs.com/ChainZhang/p/7058904.html
Copyright © 2020-2023  润新知