通过 nuget 安装 UEditorNetCore
从 UEditor 官网 下载最新的包 ueditorx_x_x_x-utf8-net.zip
解压包,并复制到项目的 wwwroot/lib 目录下,删除 net 目录。
根据 UEditorNetCore 官方的使用说明进行操作
步骤中,控制器 UEditorController 接替原 controller.ashx 的功能,用于统一处理上传逻辑
原 config.json 复制到项目根目录,用于配置上传相关设置(若更改文件名和路径在 services.AddUEditorService() 中处理)。
个人喜欢将 xxxPathFormat 值改为:upload/ueditor/{yyyy}{mm}{dd}/{time}{rand:6},方便日后迁移附件后进行批量替换。
记得配置 catcherLocalDomain 项。
上传相关的身份验证和授权控制请在 UEditorController 中处理,如:
public void Do()
{
if (用户未登录) { throw new System.Exception("请登录后再试"); }
_ue.DoAction(HttpContext);
}如果图片仅仅上传到网站目录下,那么这样配置就结束了,如果要上传到阿里云 OSS 等第三方图床,那么继续往下看。
因 UEditorNetCore 虽然实现了上传到 FTP 和 OSS 的功能,但未提供配置相关的账号信息的途径,所以只能(1)重写 action,或(2)下载 github 的源代码,将核心项目加入到您的项目中进行修改。
重写 action 不方便后期维护,这里记录修改源码的方式。
将源码改造为可配置账号的上传到 OSS 的功能,具体步骤如下:
将 Consts.cs 从项目中排除。
打开 Handlers/UploadHandler.cs,找到 UploadConfig 类,将
FtpUpload 改为 OssUpload,
FtpAccount 改为 OssAccessKeyId,
FtpPwd 改为 OssAccessKeySecret,
FtpIp 改为 OssAccessEndpoint,
再添加一个属性 OssBucketName。
打开 Handlers/UploadHandler.cs,找到 Process() 方法,
将 UploadConfig.FtpUpload 改为 UploadConfig.OssUpload,
将 Consts.AliyunOssServer.* 改为 UploadConfig.Oss*。
打开 Handlers/CrawlerHandler.cs,找到 Fetch() 方法,
将 Config.GetValue<bool>("catcherFtpUpload") 改为 Config.GetValue<bool>("OssUpload"),
将 Consts.AliyunOssServer.* 改为 Config.GetString("Oss*")。
打开 UEditorActionCollection.cs,找到 UploadImageAction,将
FtpUpload = Config.GetValue<bool>("imageFtpUpload"), FtpAccount = Consts.ImgFtpServer.account, FtpPwd = Consts.ImgFtpServer.pwd, FtpIp = Consts.ImgFtpServer.ip,替换为
OssUpload = Config.GetValue<bool>("OssUpload"), OssAccessKeyId = Config.GetString("OssAccessKeyId"), OssAccessKeySecret = Config.GetString("OssAccessKeySecret"), OssAccessEndpoint = Config.GetString("OssAccessEndpoint"), OssBucketName = Config.GetString("OssBucketName"),其余 3 个 Action(UploadScrawlAction、UploadVideoAction、UploadFileAction)按同样的方式修改。
在所有创建 UploadHandler 对象时补充添加 SaveAbsolutePath 属性。
打开 config.json,添加相关配置项(注:配置文件中的 *FtpUpload 全部废弃,统一由 OssUpload 决定)
"OssUpload": true, "OssAccessEndpoint": "", "OssAccessKeyId": "", "OssAccessKeySecret": "", "OssBucketName": "",将 xxxUrlPrefix 的值改为 OSS 对应的 CDN 网址(以 / 结尾,如://cdn.xoyozo.net/)。
其它注意点:
若使用 UEditorNetCore github 提供的源代码类库代替 nuget,且使用本地存储,那么需要将 Handlers 目录中与定义 savePath 相关的代码(查找 var savePath)替换成被注释的行
核心文件路径:/theme/html/demo*/src/js/components/core.datatable.js
所有参数的默认值见该文件 3369 行起。
data:
| 属性 | 功能 | 值 |
| type | 数据源类型 | local / remote |
| source | 数据源 | 链接或对象(见下方) |
| pageSize | 每页项数 | 默认 10 |
| saveState | 刷新、重新打开、返回时仍保持状态 | 默认 true |
| serverPaging | 是否在服务端实现分页 | 默认 false |
| serverFiltering | 是否在服务端实现筛选 | 默认 false |
| serverSorting | 是否在服务端实现排序 | 默认 false |
| autoColumns | 为远程数据源启用自动列功能 | 默认 false |
| attr |
data.source:
| 属性 | 功能 | 值 |
| url | 数据源地址 | |
| params | 请求参数 |
|
| headers |
自定义请求的头 |
|
| map | 数据地图,作用是对返回的数据进行整理和定位 |
|
layout:
| 属性 | 功能 | 值 |
| theme | 主题 | 默认 default |
| class | 包裹的 CSS 样式 | |
| scroll | 在需要时显示横向或纵向滚动条 | 默认 false |
| height | 表格高度 | 默认 null |
| minHeight | 表格最小高度 | 默认 null |
| footer | 是否显示表格底部 | 默认 false |
| header | 是否显示表头 | 默认 true |
| customScrollbar | 自定义的滚动条 | 默认 true |
| spinner |
Loading 样式 |
|
| icons | 表格中的 icon |
|
| sortable | 是否支持按列排序 | 默认 true |
|
resizable |
是否支持鼠标拖动改变列宽 | 默认 false |
| filterable | 在列中过滤 | 默认 false |
|
pagination |
显示分页信息 | 默认 true |
|
editable |
行内编辑 | 默认 false |
|
columns |
列 | 见本文下方 |
|
search |
搜索 |
|
layout.columns:
| 属性 | 功能 | 解释 |
| field | 字段名 | 对应 JSON 的属性名,点击表头时作为排序字段名 |
| title | 表头名 | 显示在表格头部 |
| sortable | 默认排序方式 | 可选:'asc' / 'desc' |
| width | 单元格最小宽度 | 值与 CSS 值一致,填数字时默认单位 px |
| type | 数据类型 | 'number' / 'date' 等,与本地排序有关 |
| format | 数据格式化 | 例格式化日期:'YYYY-MM-DD' |
| selector | 是否显示选择框 | 布尔值或对象,如:{ class: '' } |
| textAlign | 文字对齐方式 | 'center' |
| overflow | 内容超过单元格宽度时是否显示 | 'visible':永远显示 |
| autoHide | 自适应显示/隐藏 | 布尔值 |
| template | 用于显示内容的 HTML 模板 | function(row) { return row.Id; } |
| sortCallback | 排序回调 | 自定义排序方式,参 local-sort.js |
其它:
| 属性 | 功能 | 解释 |
| translate | 翻译 |
参 core.datatable.js 3512 行,简体中文示例:
|
| extensions |
暂时没有找到对字符串内容进行自动 HTML 编码的属性,这可能带来 XSS 攻击风险,在 remote 方式中必须在服务端预先 HtmlEncode。即使在 layout.columns.template 中进行处理也是无济于事,恶意代码会在 ajax 加载完成后立即执行。
方法和事件:待完善。
更多信息请查询官方文档:https://keenthemes.com/keen/?page=docs§ion=html-components-datatable
发现主力:
筹码集中(未必是主力)且获得30%仍未出货,确定是主力。

买入方法:
破位买入法、回调买入法(推荐)
注意必须结合其他功能指标:主力雷达拐头向上、AI机构活跃度重新活跃

卖出方法:
底部筹码松动时减仓,筹码峰转移到上方时平仓。

实战案例:




如果富士施乐 DocuPrint P118 w 打印机开启后电脑无法连接,但路由器上显示已连网,很有可能是 IP 已变更(增添新设备后抢占了打印机原来的 IP 地址)。
这时候需要重新安装打印机驱动:(可能有不需要重装驱动的方法)
富士施乐 DocuPrint P118 w 在安装驱动时需要路由器支持 WPS/AOSS,
但小米路由器 Pro 中找不到该功能,而且实测无线方式安装打印机驱动失败。
我的方法是,找一台 TP-LINK 路由器,
将 SSID 和 WIFI 密码改成与小米路由器相同,
关闭小米路由器,
电脑连接这个 SSID,
然后按无线的方式安装打印机驱动程序,
完成后,关闭 TP-LINK 路由器,打开小米路由器,
网络启动后,重启打印机。
(打印时可能需要在窗口中选择另一个打印机名称)
protected void Page_Load(object sender, EventArgs e)
{
int a = 1;
Task.Run(() =>
{
a = PlusOne(1);
}).Wait(3000);
b = a;
}
private static int PlusOne(int n)
{
System.Threading.Thread.Sleep(4000);
return n + 1;
}上例中使用 Task.Run 创建一个新线程调用 PlusOne 方法,并设置超时时间为 3000 毫秒。若方法 PlusOne 在 3 秒内完成,则变量 a 加 1 成功,否则 a 仍为原值。
注意:Wait 方法作用是在指定时间内等待 Task.Run 执行完毕,并不会在超时后终止该线程。
这个现象在国产浏览器上使用极速内核时出现,原因是百度编辑器上传图片功能通过 <form /> 提交到 <iframe /> 时,因跨域导致 cookie 丢失。
ASP.NET 的 ASP.NET_SessionId 默认的 SameSite 属性值为 Lax,将其设置为 None 即可:
protected void Session_Start(object sender, EventArgs e)
{
// 解决在部分国产浏览器上使用百度编辑器上传图片时(iframe),未通过 cookie 传递 ASP.NET_SessionId 的问题
string ua = Request.UserAgent ?? "";
var browsers = new string[] { "QQBrowser/" /*, "Chrome/" 不要直接设置 Chrome,真正的 Chrome 会出现正常页面不传递 Cookie 的情况 */ };
bool inWeixin = ua.Contains("MicroMessenger/"); // 是否在微信中打开(因微信PC端使用QQ浏览器内核,下面的设置会导致其网页授权失败)
if (browsers.Any(c => ua.Contains(c)) && !inWeixin)
{
Response.Cookies["ASP.NET_SessionId"].SameSite = SameSiteMode.None;
}
}以上代码加入到 Global.asax 的 Session_Start 方法中,或百度编辑器所在页面。
注意一:SameSite=None 时会将父页面的 cookie 带入到 iframe 子页的请求中,从而导致 cookie 泄露,请确保项目中无任何站外引用,如网站浏量统计器、JS组件远程CDN等!
注意二:微信PC版的内嵌浏览器使用QQ浏览器内核,以上代码会导致其微信网页授权不能正常执行。
2020年5月30日,AddTrust External CA Root 过期,虽然不影响客户端浏览器访问网站,但服务器端调用接口(file_get_contents)会出现问题,原因是证书链中根证书过期(必须使用检测工具检查服务端的证书链,而不是查看客户端浏览器上的证书信息,因为客户端浏览器上看到的的根证书是客户端系统上的根证书,是随着系统自动更新的)。

这里,Windows Server 的 IIS 与 CentOS 中的 nginx 又有所区别,咱们分开来讲:
如何更新 Windows Server 的 IIS 中的网站的根证书?
Windows Server 本身相当于一个客户端,会自动更新根证书,只不过 IIS 中的网站证书未同步更新。
打开 IIS,进入对应网站的“绑定”界面,重新绑定即可生效。简单的方法是简单修改主机名,确定,再改回原主机名,确定。

如何更新 CentOS 的 nginx 中的网站的根证书?
nginx 中使用的域名证书(pem 文件),即 conf 文件中设置的 ssl_certificate 路径对应的证书文件,是包含根证书信息的:

因此保留第一段域名证书信息,用新的根证书信息替换掉除第一段的其它内容即可。
ASP.NET MVC 使用 Authorize 过滤器验证用户登录。Authorize 过滤器首先运行在任何其它过滤器或动作方法之前,主要用来做登录验证或者权限验证。
示例:使用 Authorize 过滤器实现简单的用户登录验证。
1、创建登录控制器 LoginController
/// <summary>
/// 登录控制器
/// </summary>
[AllowAnonymous]
public class LoginController : Controller
{
/// <summary>
/// 登录页面
/// </summary>
public ActionResult Index()
{
return View();
}
/// <summary>
/// 登录
/// </summary>
[HttpPost]
public ActionResult Login(string loginName, string loginPwd)
{
if (loginName == "admin" && loginPwd == "123456")
{
// 登录成功
Session["LoginName"] = loginName;
return RedirectToAction("Index", "Home");
}
else
{
// 登录失败
return RedirectToAction("Index", "Login");
}
}
/// <summary>
/// 注销
/// </summary>
public ActionResult Logout()
{
Session.Abandon();
return RedirectToAction("Index", "Login");
}
}注意:在登录控制器 LoginController 上添加 AllowAnonymous 特性,该特性用于标记在授权期间要跳过 AuthorizeAttribute 的控制器和操作。
2、创建登录页面
@{
ViewBag.Title = "登录页面";
Layout = null;
}
<h2>登录页面</h2>
<form action='@Url.Action("Login","Login")' id="form1" method="post">
用户:<input type="text" name="loginName" /><br />
密码:<input type="password" name="loginPwd" /><br />
<input type="submit" value="登录">
</form>效果图:

3、创建主页控制器 LoginController
public class HomeController : Controller
{
public ActionResult Index()
{
// 获取当前登录用户
string loginName = Session["LoginName"].ToString();
ViewBag.Message = "当前登录用户:" + loginName;
return View();
}
}4、创建主页页面
@{
ViewBag.Title = "Index";
Layout = null;
}
<h2>Index</h2>
<h3>@ViewBag.Message</h3>
<a href="@Url.Action("Logout","Login")">注销</a>效果图:

5、创建授权过滤器 LoginAuthorizeAttribute 类
创建 Filter 目录,在该目录下创建授权过滤器 LoginAuthorizeAttribute 类,继承 AuthorizeAttribute。
using System.Web.Mvc;
namespace MvcApp.Filter
{
/// <summary>
/// 授权过滤器
/// </summary>
public class LoginAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
// 判断是否跳过授权过滤器
if (filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true)
|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true))
{
return;
}
// 判断登录情况
if (filterContext.HttpContext.Session["LoginName"] == null || filterContext.HttpContext.Session["LoginName"].ToString()=="")
{
//HttpContext.Current.Response.Write("认证不通过");
//HttpContext.Current.Response.End();
filterContext.Result = new RedirectResult("/Login/Index");
}
}
}
}通常 Authorize 过滤器也是在全局过滤器上面的,在 App_Start 目录下的 FilterConfig 类的 RegisterGlobalFilters 方法中添加:
using System.Web;
using System.Web.Mvc;
using MvcApp.Filter;
namespace MvcApp
{
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
// 添加全局授权过滤器
filters.Add(new LoginAuthorizeAttribute());
}
}
}Global.asax 下的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace MvcApp
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}xoyozo:暂时没有按区域(Area)来统一配置的方法,建议加在 Controller 上。https://stackoverflow.com/questions/2319157/how-can-we-set-authorization-for-a-whole-area-in-asp-net-mvc
在升级 kernel 后若无法启动系统,网站无法打开,SSH 无法连接,无法 ping 通。
使用 VNC 进入操作界面:

一种界面是可选择次新的内核版本:

应该能正常启动。
另一种界面提示:
Give root password for maintenance
输入密码后可启动。
阿里云工程师的建议:
1、当前默认是以最新内核启动的,由于新版内核文件存在异常无法正常运行,在手动选择低内核版本启动后,可以先更改下默认内核引导顺序,配置默认使用低版本内核运行,避免重启再次出现问题。 修改内核引导顺序 https://help.aliyun.com/knowledge_detail/41463.html 2、升级内核本身属于高危操作,建议操作前先做好快照备份,同时更新时可以参考下文档方案 避免Linux实例升级内核系统无法启动的方法 https://help.aliyun.com/knowledge_detail/59360.html

---------------------------
Microsoft Visual Studio
---------------------------
无法加载“*.edmx”: 无法将类型为“MySql.Data.MySqlClient.MySqlProviderServices”的对象强制转换为类型“System.Data.Common.DbProviderServices”。
---------------------------
解决方法:
检查 Web.config <providers> 标签是否为重复的 MySql.Data.MySqlClient。
本例中发现一个为 Version=8.0.19,一个为 Version=8.0.19.0,实践保留 Version=8.0.19.0 的 <provider> 即可。