获取
在 NuGet 中搜索 ZXing.Net
简单示例
var qr = new ZXing.QrCode.QRCodeWriter();
var matrix = qr.encode("http://xoyozo.net/", ZXing.BarcodeFormat.QR_CODE, 200, 200);
var writer = new ZXing.BarcodeWriter()
{
Format = ZXing.BarcodeFormat.QR_CODE
};
Bitmap bitmap = writer.Write(matrix);
扩展示例
string content = "http://xoyozo.net/";
var hints = new Dictionary<ZXing.EncodeHintType, object>();
hints.Add(ZXing.EncodeHintType.ERROR_CORRECTION, ZXing.QrCode.Internal.ErrorCorrectionLevel.H); // 纠错级别
hints.Add(ZXing.EncodeHintType.CHARACTER_SET, Encoding.Default.WebName); // 编码:gb2312
hints.Add(ZXing.EncodeHintType.MARGIN, 0); // 出血码元数(标准为 4,美观为 2)
var qr = new ZXing.QrCode.QRCodeWriter();
var matrix = qr.encode(content, ZXing.BarcodeFormat.QR_CODE, 200, 200, hints);
var writer = new ZXing.BarcodeWriter()
{
Format = ZXing.BarcodeFormat.QR_CODE,
Renderer = new ZXing.Rendering.BitmapRenderer
{
Foreground = Color.Black, // 前景色(默认黑色)
Background = Color.White, // 背景色(默认白色)
},
};
Bitmap bitmap = writer.Write(matrix);
将 Bitmap 写入到流
Stream stream = new MemoryStream();
bitmap.Save(stream, ImageFormat.Png);
将 Bitmap 保存到磁盘
string path = "D:\wwwroot\upload\abc.png";
bitmap.Save(path, ImageFormat.Png);
更多
对比 ThoughtWorks.QRCode 和 ZXing.Net
获取
在 NuGet 中搜索 ThoughtWorks.QRCode
简单示例
var qr = new ThoughtWorks.QRCode.Codec.QRCodeEncoder();
Bitmap bitmap = qr.Encode("http://xoyozo.net/");
扩展示例
string content = "http://xoyozo.net/";
var qr = new ThoughtWorks.QRCode.Codec.QRCodeEncoder
{
// 纠错级别,L (7%)、M (15%)、Q (25%)、H (30%)
QRCodeErrorCorrect = ThoughtWorks.QRCode.Codec.QRCodeEncoder.ERROR_CORRECTION.H,
// 码元尺寸(像素)
QRCodeScale = 4,
// 前景色(默认黑色)
QRCodeForegroundColor = Color.Black,
// 背景色(默认白色)
QRCodeBackgroundColor = Color.White,
};
// 根据内容确定 Mode,参:http://en.wikipedia.org/wiki/QR_code#Storage
if (Regex.IsMatch(content, @"^\d+$"))
{
qr.QRCodeEncodeMode = ThoughtWorks.QRCode.Codec.QRCodeEncoder.ENCODE_MODE.NUMERIC;
}
else if (Regex.IsMatch(content, @"^[0-9A-Z $%*+-./:]+$"))
{
qr.QRCodeEncodeMode = ThoughtWorks.QRCode.Codec.QRCodeEncoder.ENCODE_MODE.ALPHA_NUMERIC;
}
else
{
qr.QRCodeEncodeMode = ThoughtWorks.QRCode.Codec.QRCodeEncoder.ENCODE_MODE.BYTE;
}
Bitmap bitmap = qr.Encode(content, Encoding.Default); // 编码,简体中文系统默认为 gb2312
裁切掉多余的 1 像素
ThoughtWorks.QRCode 生成的四周没有留白的二维码图片,其右边和下边分别会多出 1 像素,使用以下方法来调整图片大小
// 创建一个新的图片(宽度和高度各缩小 1 像素)
Bitmap bitmap2 = new Bitmap(bitmap.Size.Width - 1, bitmap.Size.Height - 1);
// 以新图片来绘图
Graphics g2 = Graphics.FromImage(bitmap2);
// 新旧图片绘制到新图片中(左上角对齐)
g2.DrawImage(bitmap, 0, 0);
将 Bitmap 写入到流
Stream stream = new MemoryStream();
bitmap.Save(stream, ImageFormat.Png);
若已裁切 1 像素,请修改为 bitmap2
将 Bitmap 保存到磁盘
string path = "D:\wwwroot\upload\abc.png";
bitmap.Save(path, ImageFormat.Png);
若已裁切 1 像素,请修改为 bitmap2
更多
对比 ThoughtWorks.QRCode 和 ZXing.Net
ThoughtWorks.QRCode | ZXing.Net | |
生成方式 | 以指定的码元大小、版本、模式、纠错级别等信息来确定最终生成的图片大小 | 指定图片大小后,自动调整码元大小、出血* |
关于图片尺寸 | 不能直接确定最终生成的二维码图片的尺寸,可以先反向估算码元大小,再微调码元大小,直到不小于目标尺寸,如果必须严格限制尺寸,建议在 jpg 方式处理,因为 png 二维码的每个像素点非 0 即 1,在小尺寸的情况下会导致无法识别。(涉及到多次生成二维码,请斟酌性能消耗) | 生成二维码时即指定图片大小,但会留白,比较难以掌控实际效果 |
"BUG" | 右边和下边有多余 1 像素需要手动去除 | 虽然可以设置参数 EncodeHintType.MARGIN,但还是没有达到预期的效果(网上有解析原因,请自行搜索) |
…… |
*出血:为了提高二维码识别度,在生成的二维码四周留出若干码元(建议 4 个)空白。
更多
状态:正在连接 *.*.*.*:21...
状态:连接建立,等待欢迎消息...
响应:220-FileZilla Server
响应:220-written by Tim Kosse (tim.kosse@filezilla-project.org)
响应:220 Please visit https://filezilla-project.org/
命令:AUTH TLS
错误:无法连接到服务器
最终,没有连接到任何服务器。
服务端已允许被动连接,并且 VS 中的网站发布功能正常(FTP 方式),所以从 FileZilla 客户端入手查找问题。
在站点管理器中发现“加密”项,默认是“如果可用,使用显式的 FTP over TLS”,更改为“只使用普通 FTP (不安全)”即可连接。
这个问题一般出现在换了网络环境的情况下,研究一下 FTP over TLS 很有必要。
打开 FillZilla Server - Edit - Settings - 切换到 FTP over TLS settings 选项卡
勾选 Enable FTP over TLS support (FTPS),点击 Generate new certificate...
填写需要生成的证书信息,其中“2-Digit country code”和“Save key and certificate to this file”必填,点击 Generate certificate 完成生成证书。
完成配置后 FillZilla Server 已支持 FTPS,启动页上的警告也会随之不见:
Warning: FTP over TLS is not enabled, users cannot securely log in.
Session 有多种存储模式,默认是 InProc
,顾名思义是“在进程内”,即在 IIS 中,随网站重启而重启,网站发布后(或改动 .dll 文件)会导致应用重新运行,Session 清空。
Session 可以使用 StateServer
来保存,需要服务器开启 ASP.NET State Service 服务,此种方式要求保存在 Session 的信息必须序列化,然后从 Session 中获取的时候也要反序列化,这就导致性能有略微的损失。
Session 还可以配置为 SQLServer
,将 Session 存储在数据库中,同样需要序列化。
当配置为 Custom
时,可以在使用 Memcached、Redis 等第三方缓存技术来实现 Session 的管理,本文不作讨论。
Off
模式即关闭 Session,这种方式如果要实现用户登录功能,就必须依赖 Cookie 等来实现。
下面针对常见的三种模式进行比较:
InProc | StateServer | SQLServer | |
存储位置 | 应用进程内 | ASP.NET State Service 服务 | SQL Server 数据库 |
远程存储 | 不支持 | 支持 | 支持 |
存储格式 | 任意 | 序列化的 | 序列化的 |
可能导致重启(丢失)的情况 | 配置文件中 processModel 标签的 memoryLimit 属性; Global.asax 或者 Web.config 文件被更改; Bin 文件夹中的 Web 程序(DLL)被修改; 杀毒软件扫描了一些 .config 文件; 系统资源紧张进行资源回收导致 IIS 进程崩溃或重启等。 | ASP.NET State Service 服务停止; | - |
Session_End() 事件 | 有 | 无 | 无 |
部署难度 | 无 | 简单 | 稍复杂 |
Web.config 配置示例 (<system.web> 节点内) | <sessionState mode="InProc" /> | <sessionState mode="StateServer" /> | <sessionState mode="SQLServer" sqlConnectionString ="data source=x.x.x.x; user id=[user]; password=[pwd]" /> |
因此,如果你仅仅为了标题所述的“每次发布后丢失 Session”而烦恼,那么推荐使用 StateServer
模式来存储 Session。
注:
如果 Session 的 Key 是在应用启动时随机生成的话,使用 StateServer 和 SQLServer 还是会“丢失” Session。
这是对 Session 的配置,对 Cache 无效。
经常会看到这样似错非错的提示:
当前上下文中不存在名称"__o"
The name '__o' does not exist in the current context
实际上,我没有定义任何名为 __o 的变量。
发生这种情况的原因可能是使用了类似如下的代码:
<% if(true) { %>
<%= 1 %>
<% } %>
<%= 2 %>
为了在设计界面的 <%= %> 代码块中提供智能感知,ASP.NET(VB 或 C#)会自动生成一个名为“__o”的临时变量,这在页面编译器看到第一个 <%= %> 块时就完成了。但是在这里,<%= %> 块在 if 中出现,所以当关闭 if 后再使用 <%= %> 时,变量超出了定义的范围。
if (true)
{
object @__o;
@__o = 1;
}
@__o = 2;
解决方法:在页面的早期添加一个虚表达式。例如:<%= "" %>。这将不会呈现任何内容,并且它将确保在任何潜在的 if(或其他范围界定)语句之前,在 Render 方法中将 __o 声明为顶级。
当然还有一种治标不治本的方法就是隐藏这些错误提示(这并不影响程序正常运行):
点击错误列表面板左上角的过滤器按钮,CS0103,其中包含错误代码:当前上下文中不存在名称"__o",这些错误将不再显示,您仍然可以有其他 IntelliSense 错误和警告。
在使用 VS2017 开发 Web 的时候,有个项目突然从某一天开始,发布以后就无法“在浏览器中查看”了,会报以下错误:
必须重新生成才能正常浏览。刚开始以为是 Global.asax 出了问题,几天以后才发现,原来发布以后,bin 目录下的当前项目对应的 .dll 文件消失了!
原因找到了,那为什么发布以后会丢失这个 .dll 文件呢,而且只丢失这一个文件,如何彻底解决这个问题呢?
我现在还不知道,知道了再来告诉你们。
对于具体化的查询结果,不支持该方法。
This method is not supported against a materialized query result.
可能对嵌套查询的子结果集进行 Count() 等操作,可以在内部 select 外套一层 .ToList(),我在万条记录中测试不影响执行时间,但没有具体分析生成的 SQL 语句和执行跟踪。
收录了一些个人觉得不错的网页开发插件。
由于插件更新频繁,本页如有错误请指正,也欢迎告知更多功能强大、使用方便的插件。
插件 | 简介 | 备注 |
框架 | ||
jQuery | 最流行的 JS 框架 | 下载、中文文档、英文整合文档、中文整合文档,浏览器支持、来自 css88 的文档 官方建议 IE 6-8 使用 1.12.4 |
Angular、中文版 AngularJS (version 1.x) | 一套框架,多种平台同时适用手机与桌面 | MVC 架构,使得开发现代的单一页面应用程序(SPAs:Single Page Applications)变得更加容易 |
Vue.js | 是一套用于构建用户界面的渐进式框架。 | |
Bootstrap、中文版 | 简洁、直观、强悍的前端开发框架 | 英文文档、v3中文文档、v2中文文档、视频教程,主题和模板 |
jQuery UI | 为 jQuery 提供更丰富的功能 | 示例:Datepicker、Color Animation、Shake Effect |
功能 | ||
jQuery File Upload | jQuery 文件上传 | 英文文档 |
jQuery Cookie | 读取、写入和删除 cookie | 浏览器支持,文档 |
json2.js | json 操作库 | 已弃用,旧 IE 用 jQuery 的 parseJSON,HTML 5 用 JSON.parse |
Lightbox | 老牌图片浏览插件 推荐使用更强大的 Viewer.js | |
Swiper、中文版 | 最现代的移动触摸滑块(Most Modern Mobile Touch Slider) | 英文文档,中文文档,旧浏览器支持版本:2.x.x,Swiper 2 英文文档,中文文档 |
jquery-cropper | 图片裁剪 | |
FastClick | 用于消除手机浏览器上触摸事件触发之间的 300 毫秒延迟 | 用法,不应用的场景 |
PACE | 页面加载进度条 | 文档,IE8+ |
toastr | jQuery 通知 | 文档 |
Autosize | 一款小巧的,可自动调整 textarea 高度的独立脚本 | IE9+ |
X-editable | 允许您在页面上创建可编辑元素 | 文档,Demo |
select2 | 一款提供搜索过滤、自定义样式的下拉框插件 | |
jQuery Tags Input | 标签输入框 | 用法 |
Viewer.js | 图片浏览插件 | GitHub(viewerjs)、GitHub(jquery-viewer) jquery-viewer 是 viewerjs 的 jQuery 插件,即在 jQuery 环境中要同时引用这两个脚本。 |
PDF.js | A general-purpose, web standards-based platform for parsing and rendering PDFs. | |
编辑器 | ||
UEditor | 百度在线编辑器 | GitHub 下载、文档、ASP.NET 部署教程 |
日期时间 | ||
bootstrap-datepicker | Bootstrap 日期选择器 | Online Demo |
DateTimePicker | 日期时间选择 | |
MultiDatesPicker | 多日期选择 | |
FullCalendar | 日历日程事件工作表 | IE 9+, jQuery 2.0.0+ |
TimeTo | 计时、倒计时 | |
图表 | ||
D3.js | D3.js 是基于数据驱动文档工作方式的一款 JavaScript 函数库,主要用于网页作图、生成互动图形,是最流行的可视化库之一。 | |
Highcharts、中文版 | 兼容 IE6+、完美支持移动端、图表类型丰富、方便快捷的 HTML5 交互性图表库 | 文档 |
ECharts | 百度图表控件 | |
AntV | 来自蚂蚁金服的专业、简单、无限可能的可视化解决方案 G2 - 专业易用的可视化类库 G2-mobile - 移动端高性能可视化类库 G6 - 关系图可视化类库 | 流程图, 关系图, 可视化规范, 地图, 河流图, 力导图, 网络图, UML图, 业务流程图, 时序图 |
SyntaxHighlighter | 功能齐全的代码语法高亮插件(JS) | |
动态排名数据可视化 | 将历史数据排名转化为动态柱状图图表 开源代码,非插件,修改使用 | GitHub、视频教程、EV录屏、网页示例、视频效果 |
图标 | ||
Font Awesome | 完美的图标字体 | IE 8+,v3.2.1 支持 IE 7,进阶用法(定宽/边框/动画/旋转/叠加) |
Glyphicons | 图标字体 | 作为 Bootstrap 组件 |
Iconfont | 阿里巴巴矢量图标库 | 用户可以自定义下载多种格式的 icon,也可将图标转换为字体,便于前端工程师自由调整与调用 |
UI 框架 | ||
WeUI | 同微信原生视觉体验一致的基础样式库 | Demo、Wiki |
Apple UI Design Resources | 苹果用户界面设计资源 |
程序设计规范:
【推荐】上传的文件直接保存到文件存储服务(如阿里云 OSS),这样即使被上传了后门 shell,对网站服务器也不会有影响。
否则必须通过文件头来确定文件类型,检查文件十六进制的文件头和文件尾是否合法,并检查文件流中是否包含 php、evel 等字符。
不可直接使用客户端文件名来保存文件,特别是后缀名/扩展名。应生成随机文件名,并通过检验文件头来确定文件类型。必须由程序指定保存目录。
使用 OSS 的应直接上传,不要在 ECS 上临时存放或备份。如必须存放的,应按上述规范操作。
服务器安全设置
CentOS + nginx + PHP:
全站文件取消属性中的“执行”权限(chmod),因为这个“执行”与运行 PHP 无关。而需要上传文件的“目录”需要“执行”权限,原因是需要往该目录创建文件。
仅需要写入的目录或文件设置“写入”权限。如上传图片目录、ThinkPHP 的 Runtime 目录。
凡可写目录或文件均不允许运行 PHP / PY 等 除需要被直接访问的 PHP / PY 文件,其它动态文件均不允许被访问到,在 nginx 的配置文件中添加项,参:https://xoyozo.net/Blog/Details/nginx-location-if,若全站使用统一的入口文件访问,那么设置仅该文件允许运行 PHP 即可。通过 IO 方式被其它文件包含的文件,无需运行 PHP 权限。(“deny all”对 include 起作用,但对 IO 不起作用,因此 Runtime 目录可以继续为 ThinkPHP 提供缓存服务。)这一步非常有用。
使用与 nginx 网站用户不同的用户来部署网站文件,如宝塔面板 PHP 使用 www 用户,那么就使用 root 或其它新用户来上传文件,否则将导致全站目录和文件可写。有条件的建议不同网站使用不同的用户,可防止一个网站被入侵后导致其它网站文件或磁盘上的其它文件被泄露的风险(2022年10月2日从宝塔官方社区获悉,宝塔面板暂不支持使用非 www 用户创建并运行网站)。
Windows Server + IIS + ASP.NET:
配置每个磁盘的安全属性,拒绝“IIS_IUSRS”这个用户组的所有权限。只要设置驱动器即可,子文件夹和文件会自动继承。若运行 .NET Framework 项目,需要设置 C:\Windows\Microsoft.NET\Framework\v*.*.*****\Temporary ASP.NET Files\ 目录可修改写入权限,.NET Core 项目不需要此设置。
为每个网站创建一个新用户,仅隶属于“IIS_IUSRS”。网站根目录安全属性添加该用户,权限选择“读取”。(已测取消“读取与执行”不影响 PHP,“列出文件夹内容”视业务需求开启,建议关闭)。仅需要上传文件的目录或文件设置“修改”、“写入”权限。(修改对应修改文件,写入对应上传文件)
IIS 网站中设置“物理路径凭据”以及应用程序池的“标识”。
IIS 中设置写入目录的“处理程序映射”无脚本。