ASP.NET MVC中使用kindeditor富文本框、文件上传

在网站后台,我们经常需要发布一些信息(包含文字、图片等等)供用户查阅,这时如果有一些编辑器的使用那么就得心应手了,其实有很多第三方插件实现了此功能,
我们只需要选择性的使用即可,那么今天要介绍一款富文本编辑器的第三方插件
kindeditor

1.首先下载该插件:官网已经挂了,不知怎么回事,去搜索找找
下载完,有如下目录结构:
在这里插入图片描述
因为我是在ASP.NET MVC项目中引用的,只需如下即可,把不需要的删掉:
在这里插入图片描述
然后添加到项目中:
在这里插入图片描述
首先在asp.net文件夹中找到Demo案例,看如何使用的:

<%@ Page Language="C#" AutoEventWireup="true" validateRequest="false" %>

<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
    this.Label1.Text = Request.Form["content1"];
}

</script>

<!doctype html>

<html>
<head runat="server">
    <meta charset="utf-8" />
    <title>KindEditor ASP.NET</title>
    <link rel="stylesheet" href="../themes/default/default.css" />
	<link rel="stylesheet" href="../plugins/code/prettify.css" />
	<script charset="utf-8" src="../kindeditor.js"></script>
	<script charset="utf-8" src="../lang/zh_CN.js"></script>
	<script charset="utf-8" src="../plugins/code/prettify.js"></script>
	<script>
		KindEditor.ready(function(K) {
			var editor1 = K.create('#content1', {
				cssPath : '../plugins/code/prettify.css',
				uploadJson : '../asp.net/upload_json.ashx',
				fileManagerJson : '../asp.net/file_manager_json.ashx',
				allowFileManager : true,
				afterCreate : function() {
					var self = this;
					K.ctrl(document, 13, function() {
						self.sync();
						K('form[name=example]')[0].submit();
					});
					K.ctrl(self.edit.doc, 13, function() {
						self.sync();
						K('form[name=example]')[0].submit();
					});
				}
			});
			prettyPrint();
		});
	</script>
</head>
<body>
    <asp:Label ID="Label1" runat="server" Text=""></asp:Label>
    <form id="example" runat="server">
        <textarea id="content1" cols="100" rows="8" style="width:700px;height:200px;visibility:hidden;" runat="server"></textarea>
        <br />
        <asp:Button ID="Button1" runat="server" Text="提交内容" /> (提交快捷键: Ctrl + Enter)
    </form>
</body>
</html>

关键代码部分:

<script charset="utf-8" src="../kindeditor.js"></script>

1.首先在页面上需要引入kindeditor.js文件,我们使用捆绑包的形式,
并且引入KindEditor.ready()方法于script标签里(不要嵌套于页面加载函数里),对里面的参数进行适当修改

KindEditor.ready(function(K) {
			var editor1 = K.create('#content1', {
				cssPath : '../plugins/code/prettify.css',
				uploadJson : '../asp.net/upload_json.ashx',
				fileManagerJson : '../asp.net/file_manager_json.ashx',
				allowFileManager : true,
				afterCreate : function() {
					var self = this;
					K.ctrl(document, 13, function() {
						self.sync();
						K('form[name=example]')[0].submit();
					});
					K.ctrl(self.edit.doc, 13, function() {
						self.sync();
						K('form[name=example]')[0].submit();
					});
				}
			});
			prettyPrint();
		});
	</script>

加载富文本框:

KindEditor.ready(function(K) {...});
<form id="example" runat="server">
        <textarea id="content1" cols="100" rows="8" style="width:700px;height:200px;visibility:hidden;" runat="server"></textarea>
        <br />
        <asp:Button ID="Button1" runat="server" Text="提交内容" /> (提交快捷键: Ctrl + Enter)
    </form>
var editor1 = K.create('#content1', {.....})

content1为一textarea多行文本对象,

cssPath : '../plugins/code/prettify.css',
uploadJson : '../asp.net/upload_json.ashx',
fileManagerJson : '../asp.net/file_manager_json.ashx',

在当前项目下修改这些文件的路径

K('form[name=example]')[0].submit();

要给form表单一个属性值
所以通过以上分析可以看出,该插件是依赖于form表单下的某一textarea元素对象,
实际上就是给textarea元素绑定一个kindeditor富文本框
所以样式的修改的话还是去设置textarea对象

在BundleConfig.cs定义捆绑包:

bundles.Add(new ScriptBundle("~/js/kindeditor").Include(
"~/Content/plugin/kindeditor-4.1.6/kindeditor-all-min.js"));

案例:
我们现在想实现类似新闻信息发布的功能,管理员在后台编辑然后发布信息,供用户查阅信息

1.准备数据表NewInfos:
在这里插入图片描述
NewsId为主键自增长
isValid字段默认为true,
添加实体类:

using System;
using System.Data;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web;

namespace MVC_Project08.Models {
    public class NewInfos
    {
        [DisplayName("新闻编号")]
        public int NewsId { get; set; }
        [DisplayName("新闻标题")]
        public string NewTitle { get; set; }
        [DisplayName("新闻内容")]
        public string NewsContent { get; set; }
        [DisplayName("新闻图片")]
        public string NewsImage { get; set; }
        [DisplayName("用户编号")]
        public int UserId { get; set; }

        [DisplayName("创建时间")]
        public DateTime CreateTime { get; set; }
        [DisplayName("有效/无效 ")]
        public bool IsValid { get; set; }
        //用来接收上传的图片资源(底层是以流的方式)
        public HttpPostedFileBase newImageFile { get; set; }
        //public HttpPostedFileBase[] newImageFile { get; set; } //多文件上传
    }
}

添加News控制器,以及EditNews动作方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MVC_Project08.Models;
using System.Data.SqlClient;
using MVC_Project08.Common;
using LitJson;
namespace MVC_Project08.Controllers
{
    public class NewsController : Controller
    {
        // GET: News
        public ActionResult EditNews()
        {
            return View();
        }
    }
}

添加动作方法对应的View视图EditNews:
就相当于一个后台的编辑发布功能


@{
    Layout = null;
}

@using MVC_Project08.Models
@model NewInfos


<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>新闻编辑</title>
    @*引入JQuery类库*@
    @*<script type="text/javascript" src="~/Content/js/jquery.min.js"></script>*@

    @*加载JS捆绑包*@
    @Scripts.Render("~/js/jquery")
    @Scripts.Render("~/js/kindeditor")
    

    @*    @Scripts.Render(new string[] { "~/js/jquery","" });*@

    <script>
        KindEditor.ready(function (K) {
            var editor1 = K.create('#NewsContent', {
                cssPath: '/Content/plugin/kindeditor-4.1.6/plugins/code/prettify.css',
                uploadJson: '/Content/plugin/kindeditor-4.1.6/asp.net/upload_json.ashx',
                fileManagerJson: '/Content/plugin/kindeditor-4.1.6/asp.net/file_manager_json.ashx',
                allowFileManager: true,
                afterCreate: function () {
                    var self = this;
                    K.ctrl(document, 13, function () {
                        self.sync();
                        K('form[name=EditNews]')[0].submit();
                    });
                    K.ctrl(self.edit.doc, 13, function () {
                        self.sync();
                        K('form[name=EditNews]')[0].submit();
                    });
                }
            });
        });


        $(function () {
            debugger;
            console.log($(".ke-container.ke-container-default").length);

        });
    </script>
</head>
<body>
    <div> 

        @using (Html.BeginForm("SaveNews","News",FormMethod.Post,new {@id= "EditNews",@name = "EditNews",@enctype = "multipart/form-data" })) {

        <table>
            <tr>
                <td>@Html.DisplayNameFor(model => model.NewTitle)</td>
                <td>@Html.TextBoxFor(model => model.NewTitle)</td>

            </tr>

            <tr>
                <td>@Html.DisplayNameFor(model => model.NewsImage)</td>
                <td>
                    <input type="file" name="newImageFile" />

                    @*多文件上传name值要一样,每个文件对应后台一个HttpPostedFileBase对象 *@
                    @*<input type="file" name="newImageFile" />
                    <input type="file" name="newImageFile" />*@
                </td>
            </tr>
            <tr>
                <td>@Html.DisplayNameFor(model => model.NewsContent)</td>
                <td>@Html.TextAreaFor(model => model.NewsContent, new { @style = "width:800px;height:400px" })</td>
            </tr>
            <tr>
                <td>@Html.DisplayNameFor(model => model.CreateTime)</td>
                <td>@Html.TextBoxFor(model=>model.CreateTime,new { @class = "Wdate", @onClick = "WdatePicker({el:this,dateFmt:'yyyy-MM-dd HH:mm:ss'})" })</td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit"  value="Save"/></td>
            </tr>
        </table>
        }
    </div>
</body>
</html>

按照上述的分析修改了路径参数,但是还需要
注意:
此案例中有文件上传的功能,其表单的enctype属性必须设置为"multipart/form-data"

Result:
已成功引入,
但需要注意:
调整宽高时,还是在原textarea上进行设置,我通过css和js设置替换后的元素没有任何效果,在textarea元素设置就ok,应该是插件本身的功能所限制的吧。
在这里插入图片描述
Errors:
比如上传图片,报错信息:
在这里插入图片描述
缺少LitJson组件的引用,下载的文件有,项目添加引用,然后在控制器中引用namespace即可.

上传路径不存在的问题:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在upload_json文件中:
代码片段:

//文件保存目录路径
String savePath = "../attached/";
//文件保存目录URL(可以指定绝对路径(比如:网络路径("www.xxxxx")))
String saveUrl = aspxUrl + "../attached/";

可以看出需要在kindeditor-4.1.6目录下添加一个attached子文件夹
在这里插入图片描述

但是发现,在富文本域填写内容等信息之后,提交表单报错:
在这里插入图片描述

这是由于实际底层提交是html字符串代码,不安全,默认下在web是不允许。
解决方案:
博客链接
在提交的控制器的Action动作方法上加上[ValidateInput(false)]注解即可

在这里插入图片描述

还有就是文件作为资源文件上传,在MVC后台中使用HttpPostedFileBase类用来获取客户端上传的文件资源,一个文件对应一个HttpPostedFileBase对象,则多文件上传,就对应着HttpPostedFileBase数组,但是要保证多个文件元素的name属性值一致

//用来接收上传的图片资源(底层是以流的方式)
public HttpPostedFileBase newImageFile { get; set; }
public HttpPostedFileBase[] newImageFile { get; set; } //多文件上传

代码片段:

Html.BeginForm("SaveNews","News",...)

将后台设置的信息先保存到数据库中:

public bool AddNews(NewInfos newInfos) {
            int count = 0;
            if (newInfos!=null) {
                string sql = @"INSERT INTO NewInfos
                (NewTitle,NewsImage,NewsContent,UserId,CreateTime)
                VALUES(@NewTitle,@NewsImage,@NewsContent,@UserId,@CreateTime)";
                SqlParameter[] parameters = new SqlParameter[] {
                    new SqlParameter("@NewTitle",newInfos.NewTitle),
                    new SqlParameter("@NewsImage",newInfos.NewsImage),
                    new SqlParameter("@NewsContent",newInfos.NewsContent),
                    new SqlParameter("@UserId",10001),
                    new SqlParameter("@CreateTime",newInfos.CreateTime)
                };
               count=DBHelper.ExecuteNonQuery(sql,parameters);
            }
            return count > 0;
        }

表单提交到News控制器下的SaveNews动作方法,

     [ValidateInput(false)]
        public ActionResult SaveNews(NewInfos newInfo)
        {
            if (newInfo != null)
           {
            	//处理文件上传的信息
                //生成36位不重复字符串,拼接文件名使其不重名
                string fileName = Guid.NewGuid().ToString();
                HttpPostedFileBase hpf=newInfo.newImageFile;
                if (hpf!=null) {
                    string passedFileName = hpf.FileName;
                    int index = passedFileName.IndexOf('.');
                    string fileExtension = passedFileName.Substring(index);
                    fileName += fileExtension;
                    newInfo.NewsImage = $"Content/images/news/{fileName}";
                    string path = Server.MapPath($"~/{newInfo.NewsImage}");//拼接Web服务器地址
                    newInfo.newImageFile.SaveAs(path);//保存上传文件的内容
                }
                bool flag= AddNews(newInfo);//将新闻信息插入到数据库中
                if (flag)
                {
                    //return View("NewList");
                    //return Redirect("/News/NewList");
                    return RedirectToAction("NewList","News");
                }
                else {
                    return View("EditNews");
                }
            }
            else {
                newInfo.NewsImage = "";
            }
            return View("NewList");
        }

注意:保存上传的文件,注意是有盘符的路径:
比如本地:d://images/4.png
如果是网站文件的话,应该是 协议/ip地址(端口号)/…
所以对于mvc网站项目,项目部署这个是动态变化,需要动态获取
可以使用Server.MapPath()根据服务器动态拼接

如果新闻纪录成功添加,则重定向到NewList动作方法:
注意:
MVC中Return(viewName) -->只是查找到视图,然后把视图在正常的情况下渲染出来,不是去调用Controller下的某一个Action动作方法
如果想实现调用Action:
1.重定向Redirct()
2.重定向到某一个动作方法: RedirectToAction

public ActionResult NewList() {
  //去数据库查询出已编辑好的数据
  //ViewBag.message = "You are my destinty!";
  string sql = @"SELECT TOP 1 NewsId FROM NewInfos ORDER BY NewsId DESC";
  int newsId=(int)DBHelper.ExecuteScalar(sql);
  ViewBag.newsId =newsId;
  return View();
}

NewList视图:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>新闻列表页</title>
</head>
<body>
    <div>
        @{ 
            int newsId = ViewBag.newsId;
        }
        <p>您好,欢迎来到新闻列表页!</p>
        <a href="/News/Details/@newsId">新闻详情页</a>    
    	@*<p>Message:@ViewBag.message</p>*@
    </div>
</body>
</html>

Rasor变量值如何嵌入到html属性的问题?
直接@变量名加入即可
上面的超链接属于路由传参的方式,之前的博客也讲解过。

Details动作方法:

public ActionResult Details()
{
string newsId = RouteData.Values["id"].ToString();//获取路由参数
//去数据库查询出已编辑好的数据
ViewBag.message = "You are my destinty!";
string sql = @"SELECT * FROM NewInfos WHERE NewsId=@NewsId";
SqlParameter[] parameters = new SqlParameter[] {
    new SqlParameter("@NewsId",newsId)
};

NewInfos newInfos= DBHelper.GetModel<NewInfos>(sql,parameters);
return View(newInfos);
}

Details视图页面:

@{
    Layout = null;
}
@*强类型视图*@
@using MVC_Project08.Models
@model NewInfos
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>新闻详情页面</title>
</head>
<body>
    <div> 
       <table border="1">
           <thead>
               <tr>
                   <td colspan="2" style="color:red">新闻详细信息</td>
               </tr>
           </thead>
           <tbody>
               <tr>
                   <td>@Html.DisplayNameFor(model => model.NewTitle)</td>
                   <td>@Model.NewTitle</td>
               </tr>

               <tr>
                   <td>@Html.DisplayNameFor(model => model.UserId)</td>
                   <td>@Model.UserId</td>
               </tr>

               <tr>
                   <td>@Html.DisplayNameFor(model => model.NewsContent)</td>

                   @*@
                       Html.Raw()方法解析HTML字符串(输出时不编码)    
                   *@
                   <td>@Html.Raw(@Model.NewsContent)</td>
               </tr>
               <tr>
                   <td>@Html.DisplayNameFor(model => model.NewsImage)</td>
                   <td><img src="/@Model.NewsImage" alt="@Html.DisplayNameFor(model => model.NewsImage)"/></td>
               </tr>
               <tr>
                   <td>@Html.DisplayNameFor(model => model.CreateTime)</td>
                   <td>@Model.CreateTime</td>
               </tr>
           </tbody>
       </table>
    </div>
</body>
</html>

富文本框保存到数据库中的是底层的html字符串代码,那么在页面上又该如何解析?
在mvc HtmlHelper辅助器中,提供了一个Raw()方法可以用来解析html,输出时不进行编码:

<td>@Html.Raw(@Model.NewsContent)</td>

测试案例:
在这里插入图片描述
点击save按钮:
在这里插入图片描述
在这里插入图片描述

点击新闻详情页链接:
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值