在使用Tinymce的过程中需要用到图片上传功能,而提供的上传插件在上传文件后是给了一个连接地址,就想用户需要什么图片,不能用最直观的方式表现出来么!

虽然官网上也有一个文件管理的插件moxiemanager,可奈何他是收费的!https://www.tiny.cloud/docs/plugins/moxiemanager/

然后就打算自己弄一个,其实实现效果起来很简单,就只是做了一个类型相册管理的功能,然后在点击图片的时候,将图片的地址信息插入到编辑器里就行了,由于后台用的是layui

的框架,所以界面也就用了layui来实现,这里我只弄了上传,删除功能,也可自己添加检索等功能,实现效果如下

1 、添加插件

我们需要在tinymce的 Plugins  目录下新建一个filemanager文件夹,并添加一个名为plugin.min.js ,其中editor传参后再图片管理页面通过

var editor = top.tinymce.activeEditor.windowManager.getParams().editor; 获取编辑器对象,进行图片插入操作

tinymce.PluginManager.add("filemanager", function (editor, url) {
editor.addButton("filemanager", {
title: "图片管理",
icon: 'image',
onclick: function () {
editor.windowManager.open({
title: "图片管理",
url: "/Administrator/Filemanager/Editor",
width: window.innerWidth * 0.9,
height: window.innerHeight * 0.8
}, {
editor: editor // pointer to access editor from cshtml
})
}
})
});

  

2. 相册功能实现

文件夹管理实体类

public class FileManagerDirectoryEntity : BaseEntity
{
/// <summary>
/// 父级Id
/// </summary>
public int ParentId { get; set; } /// <summary>
/// 文件夹名称
/// </summary>
public string Name { get; set; } /// <summary>
/// 路径
/// </summary>
public string FullPath { get; set; } /// <summary>
/// 子文件数量
/// </summary>
public int ChildrenCount { get; set; }
}

  

文件管理实体类

public class FileManagerDirectoryEntity : BaseEntity
{
/// <summary>
/// 父级Id
/// </summary>
public int ParentId { get; set; } /// <summary>
/// 文件夹名称
/// </summary>
public string Name { get; set; } /// <summary>
/// 路径
/// </summary>
public string FullPath { get; set; } /// <summary>
/// 子文件数量
/// </summary>
public int ChildrenCount { get; set; }
}

  

相册功能具体实现controller

public class FileManagerController : Controller
{ #region Core
private readonly IRepository<FileManagerDirectoryEntity> _fileManagerDirectoryRepository;
private readonly IRepository<FileManagerFilesEntity> _fileManagerFilesRepository;
private const string smallImage = "_small"; public FileManagerController(
IRepository<FileManagerDirectoryEntity> fileManagerDirectoryRepository,
IRepository<FileManagerFilesEntity> fileManagerFilesRepository
)
{
this._fileManagerDirectoryRepository = fileManagerDirectoryRepository;
this._fileManagerFilesRepository = fileManagerFilesRepository;
} #endregion /// <summary>
/// 编辑器插件
/// 获取文件数据
/// </summary>
/// <param name="dirId"></param>
/// <returns></returns>
public ActionResult Editor(int dirId = 0) { List<FileManagerFileModel> modelList = new List<FileManagerFileModel>(); //加载该文件夹下的文件夹
var dirList = _fileManagerDirectoryRepository.Table
.Where(x=>x.ParentId==dirId)
.OrderByDescending(x=>x.CreateTime)
.ToList();
foreach(var item in dirList)
{ FileManagerFileModel model = new FileManagerFileModel();
model.Id = item.Id;
model.Name = item.Name;
model.FullPath = item.FullPath;
model.FileType = 2;
model.ChildrenCount = item.ChildrenCount;
modelList.Add(model);
} //加载该文件夹下的图片文件
var fileList = _fileManagerFilesRepository.Table
.Where(x => x.DirectoryId == dirId)
.OrderByDescending(x => x.CreateTime)
.ToList();
foreach (var item in fileList)
{ FileManagerFileModel model = new FileManagerFileModel();
model.Id = item.Id;
model.Name = item.Name;
model.FullPath = item.FullPath;
model.SmallFullPath = item.FullPath + smallImage + item.FileExt;
model.FileType = 1;
modelList.Add(model);
} return View(modelList);
} /// <summary>
/// 创建文件夹
/// </summary>
/// <param name="dirId"></param>
/// <returns></returns>
public ActionResult _AddDirectory(int dirId) {
return View();
} /// <summary>
/// 文件夹信息保存
/// </summary>
/// <param name="dirId"></param>
/// <param name="dirName"></param>
/// <returns></returns>
public ActionResult _AddDirectorySave(int dirId , string dirName) {
var parentDirEntity = _fileManagerDirectoryRepository.GetById(dirId);
if (!string.IsNullOrEmpty(dirName))
{
var parentDirPath = parentDirEntity == null ? "/Content/FileManager/" : parentDirEntity.FullPath;
if(parentDirEntity != null)
{
parentDirEntity.ChildrenCount++;
} FileManagerDirectoryEntity entity = new FileManagerDirectoryEntity();
entity.ParentId = dirId;
entity.Name = dirName;
entity.FullPath = string.Format("{0}/{1}/", parentDirPath, Guid.NewGuid());
if (!Directory.Exists(Server.MapPath(entity.FullPath)))
{
Directory.CreateDirectory(Server.MapPath(entity.FullPath));
} _fileManagerDirectoryRepository.Insert(entity);
_fileManagerDirectoryRepository.SaveChanges();
}
return RedirectToAction("Editor",new { dirId = dirId});
} /// <summary>
/// 上传图片
/// </summary>
/// <param name="dirId"></param>
/// <returns></returns>
public JsonResult UploadImage(int dirId)
{
//路径地址
string fileUrl = "";
var parentDirEntity = _fileManagerDirectoryRepository.GetById(dirId);
var parentDirPath = parentDirEntity == null ? "/Content/FileManager/" : parentDirEntity.FullPath; HttpFileCollectionBase postfile = HttpContext.Request.Files;
if (postfile == null)
{
return Json(new { code = 1, msg = "文件不能为空" });
} var file = postfile[0];
string extName = Path.GetExtension(file.FileName); using (System.Drawing.Image image = System.Drawing.Image.FromStream(file.InputStream))
{ string fileName = Guid.NewGuid().ToString() + extName;
string smallImgName = string.Format("{0}{1}{2}", fileName, smallImage, extName); string route = Server.MapPath(parentDirPath);
fileUrl = Path.Combine(parentDirPath, fileName);
string savePath = Path.Combine(route, fileName);
//缩略图路径
string smallImgPath = Path.Combine(route, smallImgName); //生成缩略图
try
{
ImageResizer.Fit(image, 160, 160, ImageResizeMode.Crop, ImageResizeScale.Down).Save(smallImgPath);
}
catch (Exception)
{
return Json(new { flag = false, msg = "生成缩略图出错!" });
} file.SaveAs(savePath);
} #region 添加数据到素材表
FileManagerFilesEntity entity = new FileManagerFilesEntity();
entity.FileExt = extName;
entity.FullPath = fileUrl;
entity.Name = Path.GetFileNameWithoutExtension(file.FileName);
entity.DirectoryId = dirId;
entity.Size = file.ContentLength; _fileManagerFilesRepository.Insert(entity);
_fileManagerFilesRepository.SaveChanges();
#endregion if (parentDirEntity != null)
{
parentDirEntity.ChildrenCount++;
}
_fileManagerDirectoryRepository.SaveChanges(); return Json(new { code = 0 });
} public class DeleteFilesParams
{
public int Id { get; set; } public int Type { get; set; }
} /// <summary>
/// 删除选中文件夹及图片
/// </summary>
/// <returns></returns>
public JsonResult CheckedFilesDelete(List<DeleteFilesParams> checkeds)
{
var directoryList = _fileManagerDirectoryRepository.Table.ToList();
var fileList = _fileManagerFilesRepository.Table.ToList(); foreach(var item in checkeds)
{
//删除图片
if (item.Type == 1)
{
var fileEntity = fileList.FirstOrDefault(x => x.Id == item.Id);
string path = Server.MapPath(fileEntity.FullPath);
if (System.IO.File.Exists(path))
{
System.IO.File.Delete(path);
} var parentDir = directoryList.Find(x => x.Id == fileEntity.DirectoryId);
if (parentDir != null)
{
parentDir.ChildrenCount--;
} _fileManagerFilesRepository.Delete(fileEntity);
}
else
{
var dirEntity = directoryList.FirstOrDefault(x => x.Id == item.Id);
DeleteChildDirFiles(dirEntity.Id, directoryList, fileList);
string path = Server.MapPath(dirEntity.FullPath);
if (Directory.Exists(path))
{
Directory.Delete(path, true);
} var parentDir = directoryList.Find(x => x.Id == dirEntity.ParentId);
if (parentDir != null)
{
parentDir.ChildrenCount--;
} _fileManagerDirectoryRepository.Delete(dirEntity);
}
}
_fileManagerFilesRepository.SaveChanges();
_fileManagerDirectoryRepository.SaveChanges(); return Json(new { code = 0 });
} public void DeleteChildDirFiles(int pid,List<FileManagerDirectoryEntity> dirList, List<FileManagerFilesEntity> files) {
var dirEntityList = dirList.Where(x => x.ParentId == pid);
var fileEntityList = files.Where(x => x.DirectoryId == pid);
foreach (var item in dirEntityList)
{
DeleteChildDirFiles(item.Id, dirList, files);
_fileManagerDirectoryRepository.Delete(item);
} foreach (var item in fileEntityList)
{
_fileManagerFilesRepository.Delete(item);
}
_fileManagerDirectoryRepository.SaveChanges();
_fileManagerFilesRepository.SaveChanges(); }
}

文件管理页面 Editor.chtml

 

@using Web.Areas.Administrator.Models
@model List<FileManagerFileModel>
@{
Layout = null;
} <!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>文件管理</title>
<link href="/Assets/iconfont/iconfont.css" rel="stylesheet" />
<link href="/Scripts/layui/css/layui.css" rel="stylesheet" />
<style>
body { background: #f6f6f6; }
.toolbar { padding: 10px; background: #fff; }
.toolbar i.iconfont{margin-right:10px;}
.file-list{margin:20px;}
.file-list li { float: left; background:#fff; margin-bottom:20px; margin-right:20px; }
.file-list li .img-wapper { width:160px; }
.file-list li .img-wapper img{width:100%; height:160px;}
.file-list li .file-name { padding: 0 10px; width: 100%; overflow:hidden; line-height: 30px; height:30px; color: #666; font-size: 12px; background: #fafafa; }
.file-list li .file-name .layui-form-checkbox{width:140px !important; overflow:hidden !important; }
.file-list li:hover { box-shadow: 0 0 10px rgba(0,0,0,.1); }
.file-list li:hover .file-name { background: #f5f5f5;}
</style>
</head>
<body>
<div class="toolbar">
<a class="layui-btn layui-btn-small" href="javascript:;" data-toggle="modal" data-title="新建文件夹" data-url="@Url.Action("_AddDirectory",new { dirId = Request["dirId"] == null ? 0 : int.Parse(Request["dirId"])})">
<i class="iconfont icon-directory"></i>
新建文件夹
</a>
<button id="upload-img-btn" type="button" class="layui-btn"><i class="iconfont icon-photo"></i>上传图片</button>
<button id="delete-img-btn" type="button" class="layui-btn layui-btn-danger"><i class="iconfont icon-photo"></i>删除图片</button>
</div>
<div class="layui-form">
<ul class="file-list">
@if (!string.IsNullOrWhiteSpace(Request["dirId"]))
{
<li class="file-item">
<div class="img-wapper">
<a href="javascript:history.back(-1);">
<img src="/Assets/images/default/admin_directory_back.png" alt="返回上级" title="返回上级" />
</a>
</div>
<div class="file-name">
...
</div>
</li>
}
@if (Model.Any())
{
foreach (var item in Model)
{
<li class="file-item">
@if (item.FileType == 1)
{
<div class="img-wapper">
<a href="javascript:;" class="file-img" data-url="@item.FullPath" data-title="@item.Name">
<img src="@item.SmallFullPath" title="@item.Name" />
</a>
</div>
<div class="file-name">
<input type="checkbox" name="file-id" lay-skin="primary" title="@item.Name" data-id="@item.Id" data-type="1">
</div>
}
else
{
<div class="img-wapper">
<a href="@Url.Action("Editor",new { dirId=item.Id})">
@if (item.ChildrenCount > 0)
{
<img src="/Assets/images/default/admin_directory_files.png" title="@item.Name" />
}
else
{
<img src="/Assets/images/default/admin_directory.png" title="@item.Name" />
}
</a>
</div>
<div class="file-name">
<input type="checkbox" name="file-id" lay-skin="primary" title="@item.Name" data-id="@item.Id" data-type="2">
</div>
}
</li>
}
}
</ul>
</div>
<input id="dirId" value="@Request["dirId"]" hidden>
<script src="~/Scripts/jquery-3.2.1.min.js"></script>
<script src="/Scripts/layui/layui.js"></script>
<script>
//获取tinymce编辑器
var editor = top.tinymce.activeEditor.windowManager.getParams().editor; layui.use(['upload'], function () {
var upload = layui.upload;
var dirId = $("#dirId").val() == "" ? 0 : $("#dirId").val();
upload.render({ //允许上传的文件后缀
elem: '#upload-img-btn'
, url: 'UploadImage?dirId=' + dirId
, accept: 'file' //普通文件
, multiple: true
, size: 1024 * 2 //限制文件大小,单位 KB
, exts: 'jpg|jpeg|png|gif' //只允许上传压缩文件
, done: function (res) {
if (res.code == 0) {
window.location.reload();
}
}
}); //删除图片
$("#delete-img-btn").click(function () {
var checkeds = [];
$("input[name='file-id']:checkbox").each(function () {
if (true == $(this).is(':checked')) {
checkeds.push({
id: $(this).data('id'),
type: $(this).data('type')
});
}
});
if (checkeds.length == 0) {
layer.alert('请先选择需要删除的文件!');
}
else {
layer.confirm('删除后将无法恢复,请确认是否要删除所选文件?', {
btn: ['确定删除', '我在想想'] //按钮
}, function () {
$.ajax({
type: 'post',
url: 'CheckedFilesDelete',
data: { checkeds : checkeds },
success: function (result) {
if (result.code == 0) {
window.location.reload();
}
else {
showMsg(result.msg);
}
}
})
}, function () {
});
}
})
}) //添加图片至编辑器
$(".file-img").click(function () {
var url = $(this).data("url"),
title = $(this).data("title"); //添加确认
layer.confirm('是否需要添加此图片?', {
btn: ['确认添加', '我在想想'] //按钮
}, function () {
editor.execCommand('mceInsertContent', false, '<img alt="' + title + '" src="' + url + '"/>');
editor.windowManager.close();
}, function () {});
}) </script>
<script>
//layui基本代码
$(function () {
layui.use(['element', 'form', "layer"], function () {
var element = layui.element; //表单渲染
var form = layui.form;
form.on('submit(formDemo)', function (data) {
layer.msg(JSON.stringify(data.field));
return false;
});
form.render(); //异步加载modal
$(document).on("click", '[data-toggle="modal"]', function (e) {
var $this = $(this),
url = $(this).data('url'),
title = $(this).data("title")
if (url) {
$.ajax({
url: url,
data: { rnd: Math.random() },
//dataType: 'html',
success: function (data) {
//示范一个公告层
layer.open({
type: 1
, title: title //不显示标题栏
, shade: 0.8
, shadeClose: true
, fixed: false
, area: ["900px"]
, offset: '40px'
, id: 'ajax-modal-wapper' //设定一个id,防止重复弹出
, move: false //禁止拖拽
, content: data
});
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert('加载出错。' + textStatus + '. ' + XMLHttpRequest.status);
},
complete: function () {
}
});
}
});
});
})
</script>
</body>
</html>

  

新增文件夹页面 _AddDirectory.chtml

@{
Layout = null;
} <div class="modal-content" style="padding-top:20px;">
<form class="layui-form" action="_AddDirectorySave" method="post" enctype="multipart/form-data">
<input name="dirId" value="@Request["dirId"]" hidden>
<div class="layui-form-item">
<label class="layui-form-label" for="dirName">文件夹名称</label>
<div class="layui-input-block">
<input class="layui-input" id="dirName" lay-verify="required" name="dirName" placeholder="请输入文件夹名称" type="text" value="">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="account-form" type="submit">保存信息</button>
</div>
</div>
</form>
</div>

  

3. 将选中图片插入编辑器

在图片列表的页面中,我们只需要在点击图片的事件中调用Tinymce编辑器的插入方法即可,以下为插入图片的代码

<script>
//获取tinymce编辑器
var editor = top.tinymce.activeEditor.windowManager.getParams().editor; layui.use(['upload'], function () {
var upload = layui.upload;
var dirId = $("#dirId").val() == "" ? 0 : $("#dirId").val();
upload.render({ //允许上传的文件后缀
elem: '#upload-img-btn'
, url: 'UploadImage?dirId=' + dirId
, accept: 'file' //普通文件
, multiple: true
, size: 1024 * 2 //限制文件大小,单位 KB
, exts: 'jpg|jpeg|png|gif' //只允许上传压缩文件
, done: function (res) {
if (res.code == 0) {
window.location.reload();
}
}
}); //删除图片
$("#delete-img-btn").click(function () {
var checkeds = [];
$("input[name='file-id']:checkbox").each(function () {
if (true == $(this).is(':checked')) {
checkeds.push({
id: $(this).data('id'),
type: $(this).data('type')
});
}
});
if (checkeds.length == 0) {
layer.alert('请先选择需要删除的文件!');
}
else {
layer.confirm('删除后将无法恢复,请确认是否要删除所选文件?', {
btn: ['确定删除', '我在想想'] //按钮
}, function () {
$.ajax({
type: 'post',
url: 'CheckedFilesDelete',
data: { checkeds : checkeds },
success: function (result) {
if (result.code == 0) {
window.location.reload();
}
else {
showMsg(result.msg);
}
}
})
}, function () {
});
}
})
}) //添加图片至编辑器
$(".file-img").click(function () {
var url = $(this).data("url"),
title = $(this).data("title"); //添加确认
layer.confirm('是否需要添加此图片?', {
btn: ['确认添加', '我在想想'] //按钮
}, function () {
editor.execCommand('mceInsertContent', false, '<img alt="' + title + '" src="' + url + '"/>');
editor.windowManager.close();
}, function () {});
}) </script>

 Ps: 还有很多的不足之处,希望能一起成长, 我的博客地址 jiojun.com

Tinymce 编辑器添加自定义图片管理插件的更多相关文章

  1. 推荐ajaxfilemanager for tiny_mce 比较完善的tiny_mce编辑器的图片上传及图片管理插件PHP版 支持中文

    tiny_mce编辑器,我觉得挺简洁.好用的,但就是图片上传的插件是收费的,而且网上找了半天也没有找到开源好用的上传插件. 不过功夫不负有心人,终于还就被我找到一款相当满意的插件. 这个插件的名字叫a ...

  2. TinyMCE编辑器图片上传扩展(base64方式),asp.net mvc5

    编辑器上传图片一般都是先上传到服务器中,若是用户取消或忘记提交表单就产生一张废图在空间里面,时间一长就产生大量占用空间的无用图片,现在就试试提交前先用base64,提交后,在后台处理编辑器内容中的&l ...

  3. 在线HTML文档编辑器使用入门之图片上传与图片管理的实现

    在线HTML文档编辑器使用入门之图片上传与图片管理的实现: 官方网址: http://kindeditor.net/demo.php 开发步骤: 1.开发中只需要导入选中的文件(通常在 webapp ...

  4. WordPress TinyMCE 编辑器增强技巧大全

    说到WordPress自带的TinyMCE 编辑器,有些国人总是不太满意.针对这个情况,倡萌已经介绍了一些增强或替代的方法: WordPress编辑器增强插件:TinyMCE Advanced Wor ...

  5. tinymce 编辑器 上传图片

    tinymce编辑器进行本地图片上传 首先下载tinymce.js之后 在form中添加一个<textarea>元素 给其一个id和name 然后就可以初始化编辑器了 tinymce.in ...

  6. 在Tinymce编辑器里,集成数学公式

    在以前,需要在Web页面显示数学公式,常用的都是先制作成图片,然后插入到页面里.这使得后期对数学公式的修改变的麻烦,同时也不利于搜索引擎搜索. 本文将介绍如何在TinyMce编辑器里集成数学公式.先看 ...

  7. 分享22款响应式的 jQuery 图片滑块插件

    响应式(Responsive)设计的目标是要让产品界面能够响应用户的行为,根据不同终端设备自动调整尺寸,带给用户良好的使用体验.这篇文章收集了22款优秀的响应式 jQuery 幻灯片插件,它们能够帮助 ...

  8. ImageLightbox.js – 响应式的图片 Lightbox 插件

    ImageLightbox.js 是一款很简洁的用于显示图片灯箱效果(Lightbox)的插件,没有字幕,导航按钮或默认背景.如果默认功能不够用的话,你可以很容易地自定义 JavaScript 函数扩 ...

  9. CKEditor在线编辑器增加一个自定义插件

    CKEditor是一个非常优秀的在线编辑器,它的前身就是FCKEditor,CKEditor据官方说是重写了内核的,但功能和性能比FCKEditor更为强大和优越.记得07年的时候第一次接触FCKEd ...

随机推荐

  1. linux安装spark-2.3.0集群

    (安装spark集群的前提是服务器已经配置了jdk并且安装hadoop集群(主要是hdfs)并正常启动,hadoop集群安装可参考<hadoop集群搭建(hdfs)>) 1.配置scala ...

  2. Dota2APP--第二天

    一.今天的任务 1)自定义标签栏控制器 2)自定义导航栏控制器 3)在新特性界面播放音频 1.第一个任务:自定义标签栏控制器 原因:默认的TabbarViewController不能满足项目的需求. ...

  3. 10分钟教你用Python打造天气机器人+关键字自动回复+定时发送

    01 前言 Hello,各位小伙伴.自上次我们介绍了Python实现天气预报的功能以后,那个小程序还有诸多不完善的地方,今天,我们再次来完善一下我们的小程序.比如我们想给机器人发“天气”等关键字,它就 ...

  4. 架构师养成记--16.disruptor并发框架中RingBuffer的使用

    很多时候我们只需要消息中间件这样的功能,那么直需要RinBuffer就可以了. 入口: import java.util.concurrent.Callable; import java.util.c ...

  5. 【JavaScript】__proto__和prototype的区别和联系【整理】

    var person={name:'ninja'}; person.prototype.sayName=function(){ return this.name; } Chrome运行结果: 提示找不 ...

  6. 【JavaScript】类继承(对象冒充)和原型继承__深入理解原型和原型链

    JavaScript里的继承方式在很多书上分了很多类型和实现方式,大体上就是两种:类继承(对象冒充)和原型继承. 类继承(对象冒充):在函数内部定义自身的属性的方法,子类继承时,用call或apply ...

  7. FlowPortal-BPM——验证控件

    自上而下依次是: 非空验证.范围验证.规则表达式验证.比较验证.自定义验证 非空验证的使用: 1.ControlToValidate - 监控的控件 2.ErrorMessage - 为空时提示信息

  8. Vue 不睡觉教程1-从最土开始

    目标最近在学习vue的过程中发现网上的vue教程总有些不同的问题,有的教程上来只说语法,有的教程上来就用vue-cli来建项目,但是vue-cli是整合了webpack等多个插件的工具,不利于我们学习 ...

  9. 【算法笔记】A1063 Set Similarity

    1063 Set Similarity (25 分)   Given two sets of integers, the similarity of the sets is defined to be ...

  10. 认识CSS3新增选择器和样式

    前端之HTML5,CSS3(二) CSS3新增选择器和样式 CSS3新增选择器 结构伪类选择器 :first-child:选取父元素中的第一个子元素的指定选择器 :last-child:选取父元素中的 ...