富文本编辑器bootstrap-wysiwyg

 

 之前demo相关博客查看的,只有3.x多的版本才有这些图标显示出来。应该是某些属性是用的老的样式,新版的没研究,先用这3.x版本的 font-awesome 吧。

font-awesome 下载地址:

https://www.bootcdn.cn/font-awesome/

 热键相关js 下载地址:

https://plugins.jquery.com/hotkeys/

需要引入css:

    <link  th:href="@{/css/bootstrap-combined.no-icons.min.css}" rel="stylesheet"/>
    <link  th:href="@{/bootstrap-4.4.1-dist/css/bootstrap.min.css}" rel="stylesheet" type="text/css" />
    <link  th:href="@{/css/font-awesome.css}" rel="stylesheet"/>
    <link  th:href="@{/css/index.css}" rel="stylesheet"/>

js:

<script    th:src="@{/js/jquery-3.4.1.min.js}"></script>
<!--键盘事件-->
<script    th:src="@{/js/jquery.hotkeys.js}"></script>
<!--bootstrap.bundle.min.js此文件包含Popper.min.js,只是点击下拉框需要双击才行-->
<!--<script th:src="@{/bootstrap-4.4.1-dist/js/bootstrap.bundle.min.js}"></script>-->
<!--富文本编辑框点击文字样式,和大小,下拉框没反应是因为没引入popper.min.js的问题。-->
<script  th:src="@{/js/popper.min.js}"></script>
<script    th:src="@{/bootstrap-4.4.1-dist/js/bootstrap.min.js}"></script>
<!--<script    th:src="@{/js/bootstrap-wysiwyg.js}"></script>-->
<script    th:src="@{/js/bootstrap-wysiwyg-define.js}"></script>

整体demo页面html:

  1 <!DOCTYPE html>
  2 <html lang="en" xmlns:th=http://www.thymeleaf.org>
  3 <head>
  4     <meta charset="UTF-8">
  5     <title>编辑新闻详情页面</title>
  6     <link  th:href="@{/css/bootstrap-combined.no-icons.min.css}" rel="stylesheet"/>
  7     <link  th:href="@{/bootstrap-4.4.1-dist/css/bootstrap.min.css}" rel="stylesheet" type="text/css" />
  8     <link  th:href="@{/css/font-awesome.css}" rel="stylesheet"/>
  9     <link  th:href="@{/css/index.css}" rel="stylesheet"/>
 10     <style>
 11 
 12         .editor-container { /* 编辑器容器样式 */
 13 
 14                 padding: 25px 20px 25px;
 15 
 16                 margin-bottom: 10px;
 17 
 18                 background-color: #eeeeee;
 19 
 20                 -webkit-border-radius: 6px;
 21 
 22                 -moz-border-radius: 6px;
 23 
 24                 border-radius: 6px;
 25 
 26         }
 27 
 28          
 29 
 30         .btn-toolbar {
 31 
 32                 font-size: 0;
 33 
 34                 margin-top: 10px;
 35 
 36                 margin-bottom: 10px;
 37 
 38         }
 39 
 40          
 41 
 42         #editor { /* 编辑框样式 */
 43 
 44                 max-height: 400px;
 45 
 46                 height: 400px;
 47 
 48                 width: 100%;
 49 
 50                 background-color: white;
 51 
 52                 border-collapse: separate;
 53 
 54                 border: 1px solid rgb(204, 204, 204);
 55 
 56                 padding: 4px;
 57 
 58                 box-sizing: content-box;
 59 
 60                 -webkit-box-shadow: rgba(0, 0, 0, 0.0745098) 0px 1px 1px 0px inset;
 61 
 62                 box-shadow: rgba(0, 0, 0, 0.0745098) 0px 1px 1px 0px inset;
 63 
 64                 border-top-right-radius: 3px;
 65 
 66                 border-bottom-right-radius: 3px;
 67 
 68                 border-bottom-left-radius: 3px;
 69 
 70                 border-top-left-radius: 3px;
 71 
 72                 overflow: scroll;
 73 
 74                 outline: none;
 75 
 76         }
 77 
 78          
 79 
 80             /* 工具条里按钮样式,这个样式其实是.btn-default的样式,
 81 
 82     Button按钮之所以没有直接加上.btn-default样式是因为按钮选中后wysiwyg会给选中的按钮加.btn-info样式,
 83 
 84     .btn-default和.btn-info同时存在样式会冲突 */
 85             .btn-toolbar .btn {
 86 
 87 
 88                      color: #333;
 89 
 90                      background-color: #fff;
 91 
 92                      border-color: #ccc;
 93 
 94              }
 95 
 96          
 97 
 98             /* 这个样式其实是.btn-info的样式,重写一遍是为了提高优先级,
 99 
100     否则.btn-info的样式会被.btn-toolbar .btn覆盖,这个样式要写在.btn-toolbar .btn之下 */
101         .btn-toolbar .btn-info {
102 
103                 color: #fff;
104 
105                 background-color: #5bc0de;
106 
107                 border-color: #46b8da;
108 
109         }
110 
111     </style>
112 </head>
113 <body>
114     <div class="btn-toolbar" data-role="editor-toolbar" data-target="#editor">
115         <div class="btn-group">
116             <a class="btn dropdown-toggle" data-toggle="dropdown" title="Font"><i class="icon-font"></i><b class="caret"></b></a>
117             <ul class="dropdown-menu"> </ul>
118         </div>
119         <div class="btn-group">
120             <a class="btn dropdown-toggle" data-toggle="dropdown" title="Font Size"><i class="icon-text-height"></i> <b class="caret"></b></a>
121             <ul class="dropdown-menu">
122                 <li><a data-edit="fontSize 5"><font size="5">Huge</font></a></li>
123                 <li><a data-edit="fontSize 3"><font size="3">Normal</font></a></li>
124                 <li><a data-edit="fontSize 1"><font size="1">Small</font></a></li>
125             </ul>
126         </div>
127         <div class="btn-group">
128             <a class="btn" data-edit="bold" title="Bold (Ctrl/Cmd+B)"><i class="icon-bold"></i></a> <!--加粗-->
129             <a class="btn" data-edit="italic" title="Italic (Ctrl/Cmd+I)"><i class="icon-italic"></i></a><!-- 斜体-->
130             <a class="btn" data-edit="strikethrough" title="Strikethrough"><i class="icon-strikethrough"></i></a><!-- 删除线-->
131             <a class="btn" data-edit="underline" title="Underline (Ctrl/Cmd+U)"><i class="icon-underline"></i></a><!-- 下划线-->
132         </div>
133         <div class="btn-group">
134             <a class="btn" data-edit="insertunorderedlist" title="Bullet list"><i class="icon-list-ul"></i></a><!-- 加点-->
135             <a class="btn" data-edit="insertorderedlist" title="Number list"><i class="icon-list-ol"></i></a><!-- 数字排序-->
136             <a class="btn" data-edit="outdent" title="Reduce indent (Shift+Tab)"><i class="icon-indent-left"></i></a><!-- 减少缩进-->
137             <a class="btn" data-edit="indent" title="Indent (Tab)"><i class="icon-indent-right"></i></a><!--增加缩进-->
138         </div>
139         <div class="btn-group">
140             <a class="btn" data-edit="justifyleft" title="Align Left (Ctrl/Cmd+L)"><i class="icon-align-left"></i></a><!--左对齐-->
141             <a class="btn" data-edit="justifycenter" title="Center (Ctrl/Cmd+E)"><i class="icon-align-center"></i></a><!-- 居中 -->
142             <a class="btn" data-edit="justifyright" title="Align Right (Ctrl/Cmd+R)"><i class="icon-align-right"></i></a><!--右对齐-->
143             <a class="btn" data-edit="justifyfull" title="Justify (Ctrl/Cmd+J)"><i class="icon-align-justify"></i></a><!--垂直对齐-->
144         </div>
145         <div class="btn-group">
146             <a class="btn dropdown-toggle" data-toggle="dropdown" title="Hyperlink"><i class="icon-link"></i></a><!-- 链接-->
147             <div class="dropdown-menu input-append">
148                 <input class="span2" placeholder="URL" type="text" data-edit="createLink"/>
149                 <button class="btn" type="button">Add</button>
150             </div>
151             <a class="btn" data-edit="unlink" title="Remove Hyperlink"><i class="icon-cut"></i></a>
152         </div>
153         <div class="btn-group">
154             <a class="btn" title="Insert picture (or just drag & drop)" id="pictureBtn"><i class="icon-picture"></i></a>
155         <input type="file" id="pictureInput" name="picture" data-role="magic-overlay" data-target="#pictureBtn" data-edit="insertImage" action="/ylxtWeb/news/upload"/>
156         </div>
157         <div class="btn-group">
158             <a class="btn" data-edit="undo" title="Undo (Ctrl/Cmd+Z)"><i class="icon-undo"></i></a><!--撤销-->
159             <a class="btn" data-edit="redo" title="Redo (Ctrl/Cmd+Y)"><i class="icon-repeat"></i></a><!--恢复-->
160         </div>
161         <input type="text" data-edit="inserttext" id="voiceBtn" x-webkit-speech="">
162     </div>
163 
164     <div id="editor" contenteditable="true" th:text="${news?.content}"></div>
165     <div style="text-align: center;margin-top: 10px;">
166         <button class="btn-info" onclick="cancel()" >返回</button>
167         <button class="btn-info" onclick="clea()" style="margin: 0 36px;">清空</button>
168         <button class="btn-info" id="confirmBtn" onclick="confir()" th:attr="news_id=${news?.id}" >确定</button>
169     </div>
170 <form action="" id="myForm" style="display: none;">
171     <input type="text" name="news" th:value="${news}">
172 </form>
173 </body>
174 <script    th:src="@{/js/jquery-3.4.1.min.js}"></script>
175 <!--键盘事件-->
176 <script    th:src="@{/js/jquery.hotkeys.js}"></script>
177 <!--bootstrap.bundle.min.js此文件包含Popper.min.js,只是点击下拉框需要双击才行-->
178 <!--<script th:src="@{/bootstrap-4.4.1-dist/js/bootstrap.bundle.min.js}"></script>-->
179 <!--富文本编辑框点击文字样式,和大小,下拉框没反应是因为没引入popper.min.js的问题。-->
180 <script  th:src="@{/js/popper.min.js}"></script>
181 <script    th:src="@{/bootstrap-4.4.1-dist/js/bootstrap.min.js}"></script>
182 <!--<script    th:src="@{/js/bootstrap-wysiwyg.js}"></script>-->
183 <script    th:src="@{/js/bootstrap-wysiwyg-define.js}"></script>
184 
185 <script th:inline="javascript">
186 function cancel(){
187 window.location.href = baseUrl+"/news/toPageNews";
188 }
189 function clea(){
190     console.log(222);
191     //获取清除HTML标签后的内容:
192     $("#editor").empty();
193 }
194 
195 function confir(){
196     //获取富文本编辑器的内容,和获取普通div内容一样。
197     var cont = $("#editor").html();
198     console.log(cont);
199 
200     var news_id = $("#confirmBtn").attr("news_id");
201     var data_news=[[${news}]]
202     data_news.content = cont;
203 var formEle = document.getElementById("myForm");
204 formEle.action = baseUrl+"/news/updateNews";
205 var formData = new FormData(formEle);
206 /*Object.keys(data_news).forEach((key) => {
207 formData.append(key, data_news[key]);
208 });
209 console.log(formData.get("title")+"5555"+formData.get("isDelete"));*/
210             //formEle.submit();
211             //提交表单
212 var xhr = new XMLHttpRequest();
213 xhr.open('PUT', baseUrl+"/news", true);
214 xhr.onload = function () {
215   if (xhr.status !== 200) {
216     console.log('An error occurred!');
217   }
218 };
219 xhr.send(formData);
220 }
221 var baseUrl = "";
222 $(function(){
223         var pathName = window.location.pathname.substring(1);
224         var webName = pathName == '' ? '' : pathName.substring(0, pathName.indexOf('/'));
225         baseUrl = window.location.protocol + '//' + window.location.host+'/' + webName + '/';
226         // 初始化工具条
227         initToolbarBootstrapBindings();
228         $('#editor').wysiwyg();
229     });
230 
231     // 初始化工具条
232     function initToolbarBootstrapBindings() {
233         // 字体样式
234         var fonts = [ 'Serif', 'Sans', 'Arial', 'Arial Black', 'Courier',
235                 'Courier New', 'Comic Sans MS', 'Helvetica', 'Impact',
236                 'Lucida Grande', 'Lucida Sans', 'Tahoma', 'Times',
237                 'Times New Roman', 'Verdana' ],
238             fontTarget = $('[title=Font]').siblings('.dropdown-menu');
239         $.each(fonts,function(idx, fontName) {
240             fontTarget.append($('<li><a href="#" data-edit="fontName ' + fontName 
241                     +'" style="font-family:\''+ fontName +'\'">' + fontName + '</a></li>'));
242         });
243 
244         $('button[title]').tooltip({
245             container : 'body'
246         });
247 
248         // .dropdown-menu下的input事件
249         $('.dropdown-menu input').click(function() {
250             return false;
251         })
252         .change(function() {
253             $(this).parent('.dropdown-menu').siblings('.dropdown-toggle').dropdown('toggle');
254         })
255         .keydown('esc', function() {
256             this.value = '';
257             $(this).change();
258         });
259 
260         // [data-role=magic-overlay]的样式
261         $('[data-role=magic-overlay]').each(function() {
262             var overlay = $(this), target = $(overlay.data('target'));
263             overlay.css('opacity', 0).css('position', 'absolute')
264                     .offset(target.offset()).width(target.outerWidth())
265                     .height(target.outerHeight());
266         });
267     };
268 
269 </script>
270 </html>
View Code

查了好多博客里边的demo的图片都是没有上传到服务器的,需要修改bootstrap-wysiwyg.js文件,原理:选中图片后就上传到服务器,然后服务端返回图片访问链接,前端把链接写入img标签的src属性内,并放到编辑框内,

修改后的bootstrap-wysiwyg.js文件,更名为bootstrap-wysiwyg-define.js引入了thymeleaf模板页面。/* http://github.com/mindmup/bootstrap-wysiwyg */

/* http://github.com/mindmup/bootstrap-wysiwyg */
/*global jQuery, $, FileReader*/
/*jslint browser:true*/
(function ($) {
    'use strict';
    /*转码图片 不再使用转码,而变为使用链接src */
    var readFileIntoDataUrl = function (fileInfo) {
        var loader = $.Deferred(),  //jq延迟对象
            fReader = new FileReader();
        fReader.onload = function (e) {
            loader.resolve(e.target.result);
        };
        fReader.onerror = loader.reject; //拒绝
        fReader.onprogress = loader.notify;
        fReader.readAsDataURL(fileInfo); //转码图片
        return loader.promise();  //返回promise对象,观察某种类型被绑定到集合的所有行动,是否已被加入到队列中。
    };
    //一、修改原readFileIntoDataUrl方法
        /*var readFileIntoDataUrl = function (fileInfo) {
            var loader = $.Deferred(),
                fReader = new FileReader(),
                img = '';
            fReader.onload = function (e) {
                img = e.target.result;
                $.ajax({
                    url: ctxPath+'news/upload',
                    type: 'post',
                    async: false,
                    dataType: 'json',
                    data: {"file":fileInfo},
                    success: function(data){
                     if(data.responseCode == 1){
                    loader.resolve(服务器返回的图片的地址);
                      }else if(data.responseCode == 0){
                          alert('上传失败');
                      }
                    }
                });
            };
            fReader.onerror = loader.reject;
            fReader.onprogress = loader.notify;
            fReader.readAsDataURL(fileInfo);
            return loader.promise();
        };*/
        //直接使用Ajax上传图片
var uploadFileToServer = function(fileInfo,action, callback) {
 //var fileObj = document.getElementById("pictureInput").files[0]; // js 获取文件对象

               var tokenv="ssssssss";

               //var data = {"id":id,"picture":fileObj};
            var formData = new FormData();//document.getElementById("myForm")
            //formData.append("picture",$("#pictureInput")[0].files[0]);
            //formData.append("file",fileObj);
            formData.append("file",fileInfo);
            formData.append("token",tokenv);
console.log(formData);
 $.ajax({
  type: 'post',
  url : action,
  cache: false,
  data: formData,
  processData: false,//如果processData不設置為false,jquery會把formData轉換為字符串。
  contentType : false,//不设置是:application/x-www-form-urlencoded;
  dataType : 'json',
  success : function(obj) {
  if (obj.status) {
   callback(obj.imgsrc);
  } else
   options.fileUploadError("server-internal-exception",
    obj.message);
  },
  error : function(e) {
  console.log(e);
  //options.fileUploadErroe("upload-failure", "");
  }
 });}
    /*清空内容*/
    $.fn.cleanHtml = function () {
        var html = $(this).html();
        return html && html.replace(/(<br>|\s|<div><br><\/div>|&nbsp;)*$/, '');
    };
    $.fn.wysiwyg = function (userOptions) {
        var editor = this,  //设置ui-jq='设置的插件别名的dom元素'(此句注释可忽略,是针对我的项目结构写的)
            selectedRange,
            options,
            toolbarBtnSelector,
            //更新工具栏
            updateToolbar = function () {
                if (options.activeToolbarClass) {
                    $(options.toolbarSelector).find(toolbarBtnSelector).each(function () {
                        var command = $(this).data(options.commandRole);
                        //判断光标所在位置以确定命令的状态,为真则显示为激活
                        if (document.queryCommandState(command)) {
                            $(this).addClass(options.activeToolbarClass);
                        } else {
                            $(this).removeClass(options.activeToolbarClass);
                        }
                    });
                }
            },
            //插入内容
            execCommand = function (commandWithArgs, valueArg) {
                var commandArr = commandWithArgs.split(' '),
                    command = commandArr.shift(),
                    args = commandArr.join(' ') + (valueArg || '');
                document.execCommand(command, 0, args);
                updateToolbar();
            },
            //用jquery.hotkeys.js插件监听键盘
            bindHotkeys = function (hotKeys) {
                $.each(hotKeys, function (hotkey, command) {
                    editor.keydown(hotkey, function (e) {
                        if (editor.attr('contenteditable') && editor.is(':visible')) {
                            e.preventDefault();
                            e.stopPropagation();
                            execCommand(command);
                        }
                    }).keyup(hotkey, function (e) {
                        if (editor.attr('contenteditable') && editor.is(':visible')) {
                            e.preventDefault();
                            e.stopPropagation();
                        }
                    });
                });
            },
            //获取当前range对象
            getCurrentRange = function () {
                var sel = window.getSelection();
                if (sel.getRangeAt && sel.rangeCount) {
                    return sel.getRangeAt(0); //从当前selection对象中获得一个range对象。
                }
            },
            //保存
            saveSelection = function () {
                selectedRange = getCurrentRange();
            },
            //恢复
            restoreSelection = function () {
                var selection = window.getSelection(); //获取当前既获区,selection是对当前激活选中区(即高亮文本)进行操作
                if (selectedRange) {
                    try {
                        //移除selection中所有的range对象,执行后anchorNode、focusNode被设置为null,不存在任何被选中的内容。
                        selection.removeAllRanges();
                    } catch (ex) {
                        document.body.createTextRange().select();
                        document.selection.empty();
                    }
                    //将range添加到selection当中,所以一个selection中可以有多个range。
                    //注意Chrome不允许同时存在多个range,它的处理方式和Firefox有些不同。
                    selection.addRange(selectedRange);
                }
            },
            //插入文件(这里指图片)
                //将insertFiles方法作改写如下:
            insertFiles = function (files, action) {
                editor.focus();
                //遍历插入(应为可以多文件插入)
                $.each(files, function (idx, fileInfo) {
                    //只可插入图片文件
                    if (/^image\//.test(fileInfo.type)) {
                        //转码图片
                        /*
                       * $.when(readFileIntoDataUrl(fileInfo)).done(function(dataUrl) {
                       * execCommand('insertimage', dataUrl); }).fail(function(e) {
                       * options.fileUploadError("file-reader", e); });
                       */
                       uploadFileToServer(fileInfo,action, function(src) {
                       execCommand('insertimage', src);
                       });
                    } else {
                        //非图片文件会调用config的错误函数
                        options.fileUploadError("unsupported-file-type", fileInfo.type);
                    }
                });
            },
            //TODO 暂不了解用意
            markSelection = function (input, color) {
                restoreSelection();
                //确定命令是否被支持,返回true或false
                if (document.queryCommandSupported('hiliteColor')) {
                    document.execCommand('hiliteColor', 0, color || 'transparent');
                }
                saveSelection();
                input.data(options.selectionMarker, color);
            },
            //绑定工具栏相应工具事件
            bindToolbar = function (toolbar, options) {
                //给所有工具栏上的控件绑定点击事件
                toolbar.find(toolbarBtnSelector).click(function () {
                    restoreSelection();
                    editor.focus();  //获取焦点
                    //设置相应配置的工具execCommand
                    execCommand($(this).data(options.commandRole));
                    //保存
                    saveSelection();
                });
                //对[data-toggle=dropdown]进行单独绑定点击事件处理  字体大小
                toolbar.find('[data-toggle=dropdown]').click(restoreSelection);
                //对input控件进行单独处理,webkitspeechchange为语音事件
                toolbar.find('input[type=text][data-' + options.commandRole + ']').on('webkitspeechchange change', function () {
                    var newValue = this.value; //获取input 的value
                    this.value = '';  //清空value防止冲突
                    restoreSelection();
                    if (newValue) {
                        editor.focus();//获取焦点
                        //设置相应配置的工具execCommand
                        execCommand($(this).data(options.commandRole), newValue);
                    }
                    saveSelection();
                }).on('focus', function () { //获取焦点
                    var input = $(this);
                    if (!input.data(options.selectionMarker)) {
                        markSelection(input, options.selectionColor);
                        input.focus();
                    }
                }).on('blur', function () { //失去焦点
                    var input = $(this);
                    if (input.data(options.selectionMarker)) {
                        markSelection(input, false);
                    }
                });
                //图片按钮添加了监听器事件
                toolbar.find('input[type=file][data-' + options.commandRole + ']')
                  .change(
                   function() {
                    restoreSelection();
                    if (this.type === 'file' && this.files
                     && this.files.length > 0) {
                     insertFiles(this.files, $(this).attr('action'));
                    }
                    saveSelection();
                    this.value = '';
                    });
            },
            //初始化拖放事件
            initFileDrops = function () {
                editor.on('dragenter dragover', false)
                    .on('drop', function (e) {
                        var dataTransfer = e.originalEvent.dataTransfer;
                        e.stopPropagation();
                        e.preventDefault();
                        if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
                            //insertFiles(dataTransfer.files);
                            insertFiles(dataTransfer.files, $('input[type=file]').attr('action'));
                        }
                    });
            };
        //合并传入的配置对象userOptions和默认的配置对象config
        options = $.extend({}, $.fn.wysiwyg.defaults, userOptions);
        //设置查找字符串:a[data-edit] button[data-edit] input[type=button][data-edit]
        toolbarBtnSelector = 'a[data-' + options.commandRole + '],button[data-' + options.commandRole + '],input[type=button][data-' + options.commandRole + ']';
        //设置热键 容器有[data-role=editor-toolbar]属性的dom元素
        bindHotkeys(options.hotKeys);
        //是否允许拖放 允许则配置拖放
        if (options.dragAndDropImages) {initFileDrops();}
        //配置工具栏
        bindToolbar($(options.toolbarSelector), options);
        //设置编辑区域为可编辑状态并绑定事件mouseup keyup mouseout
        editor.attr('contenteditable', true)
            .on('mouseup keyup mouseout', function () {
                saveSelection();
                updateToolbar();
            });
        //编辑区域绑定图片点击事件
        //TODO 这是我自己添加的,因为有时要对图片进行一些操作
        editor.on('mousedown','img', function (e) {
            e.preventDefault();
        }).on('click', 'img', function (e) {
            var $img = $(e.currentTarget);
            console.log($img);
            e.preventDefault();
            e.stopPropagation();
        });
        //window绑定touchend事件
        $(window).bind('touchend', function (e) {
            var isInside = (editor.is(e.target) || editor.has(e.target).length > 0),
                currentRange = getCurrentRange(),
                clear = currentRange && (currentRange.startContainer === currentRange.endContainer && currentRange.startOffset === currentRange.endOffset);
            if (!clear || isInside) {
                saveSelection();
                updateToolbar();
            }
        });
        return this;
    };
    //配置参数
    $.fn.wysiwyg.defaults = {
        hotKeys: {      //热键 应用hotkeys.js jquery插件
            'ctrl+b meta+b': 'bold',
            'ctrl+i meta+i': 'italic',
            'ctrl+u meta+u': 'underline',
            'ctrl+z meta+z': 'undo',
            'ctrl+y meta+y meta+shift+z': 'redo',
            'ctrl+l meta+l': 'justifyleft',
            'ctrl+r meta+r': 'justifyright',
            'ctrl+e meta+e': 'justifycenter',
            'ctrl+j meta+j': 'justifyfull',
            'shift+tab': 'outdent',
            'tab': 'indent'
        },
        toolbarSelector: '[data-role=editor-toolbar]',
        commandRole: 'edit',
        activeToolbarClass: 'btn-info',
        selectionMarker: 'edit-focus-marker',
        selectionColor: 'darkgrey',
        dragAndDropImages: true,  //是否支持拖放,默认为支持
        fileUploadError: function (reason, detail) { console.log("File upload error", reason, detail); }
    };
}(window.jQuery));

 

测试图片上传和拖放都成功:

 

 后台Java接收图片方法:

   /**
     *
     * @param file  MultipartFile 这个类一般是用来接受前台传过来的文件
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/upload",method = RequestMethod.POST)
    public Map<String,Object> multiUpload(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
        Map<String,Object> res = new HashMap<String, Object>();
        try {
            String scheme = request.getScheme();//http
            String serverName = request.getServerName();//localhost
            int serverPort = request.getServerPort();//8080
            String contextPath = request.getContextPath();//项目名
            String url = scheme+"://"+serverName+":"+serverPort+contextPath;//http://127.0.0.1:8080/test

            LOGGER.info("url:"+url);
            String imgUrl = "";
            //String imgUrl=imgPath.substring(0,imgPath.length()-2);//截取到的是"/static/",如果配置访问路径的话
            String path = request.getContextPath();
            String intactPath =null;
            String filename=file.getOriginalFilename();
            String imgDir = imgServerPath.substring(imgServerPath.indexOf("file:") + 5, imgServerPath.length());
            File file2 = new File(imgDir, filename);
            LOGGER.info("imgDir:"+imgDir);
            //得到原始文件的输入流
            InputStream inputStream=file.getInputStream();
            FileOutputStream fileOutputStream=new FileOutputStream(file2);
            //写出文件
            IOUtils.copy(inputStream,fileOutputStream);
            inputStream.close();
            fileOutputStream.close();
            if(!file.isEmpty()){
                imgUrl = url+File.separator + file.getOriginalFilename();
                System.out.println(intactPath);
                int pre = (int) System.currentTimeMillis();

            }
            res.put("status","succ");
            res.put("imgsrc",imgUrl);
        } catch (Exception e) {
            res.put("status","error");
            res.put("msg",e.getMessage());
            e.printStackTrace();
            LOGGER.info("multiUpload方法异常!",e);
            System.out.println(e.getMessage());
        }
        return res;
    }

参考链接:

https://www.jb51.net/article/85252.htm

posted @ 2020-01-17 13:44  好Wu赖  阅读(874)  评论(0编辑  收藏  举报