| Midjourney | Stable Diffusion | |
| 收费情况 | 收费 | 开源免费 |
| 使用方式 | 联网 | 本地部署(保护隐私?) |
| 学习入门 | 入门简单(学习) | 学习成本较高(学习) |
| 内容质量 | 出图丰富多彩,质量高 | |
| 内容限制 | 内容有限制 | 内容无限制 |
| 可扩展性 | 可以安装插件(ControlNet 等) | |
| 电脑配置 | 电脑配置有要求(N卡) |
群晖系统暂时没有类似 TreeSize 的磁盘文件管理工具,但是我们可以用磁盘映射的方式将群晖系统上的目录挂载到电脑上。这样,在电脑上就可以用 TreeSize 扫描群晖上的磁盘文件了。具体步骤如下:
一、群晖上安装 WebDAV Server

二、启用 WebDAV Server

三、新建群晖用户

千万要设置好权限。
切换到“应用程序”选项卡,关闭除 WebDAV Server 以外的所有应用程序
切换到“权限”选项卡,勾选需要访问的目录

四、在电脑上安装 RaiDrive
从官网下载,免费版即可。
五、配置 RaiDrive
打开 RaiDrive,点击顶部的“添加”,选择“NAS”,选择“Synology”,并填相应的地址和账户

技巧:将群晖提供的外部访问地址(在 控制面板-外部访问 中查看)直接在浏览器上打开,如果与群晖在同一局域网,那么会跳转到 https://[IP].[QuickConnect ID].direct.quickconnect.cn:5001/,那么参照这个地址填入到 RaiDrive 中即可在局域网中连接;如果不在同一局域网,那么会跳转到公网地址,同样可以将公网地址填入,但必须在路由器上映射端口才能在外网映射磁盘到 NAS。
六、访问文件
一切顺利,你就可以在“此电脑”中看到新建的盘符,像访问本地磁盘一样访问群晖文件。

在代码
app.Run();处报错:
System.IO.IOException:“Failed to bind to address http://localhost:5182.”
SocketException: 以一种访问权限不允许的方式做了一个访问套接字的尝试。
原因是端口被占用,解决方法:
方法一、重启电脑可能解决该问题。
方法二、使用命令 netstat -ano 找到占用该端口的进程,关闭即可。
方法三、修改运行端口。展开解决方案资源管理器中项目根目录下的“Properties”目录,打开“launchSettings.json”,找到对应你运行方式的配置,修改相应 Url 中的端口。
| LigerShark.WebOptimizer.Core | BuildBundlerMinifier | |
| 特点 | 在运行时捆绑和缩小 CSS 和 JavaScript 文件 具有完整的服务器端和客户端缓存,以确保高性能 可禁用缩小 支持使用通配模式 标记帮助程序与缓存破坏 支持内联 支持 SCSS | 将 CSS、JavaScript 或 HTML 文件捆绑到单个输出文件中 保存源文件会自动触发重新捆绑 支持通配模式 支持 CI 方案的 MSBuild 支持 缩小单个或捆绑的 CSS、JavaScript 和 HTML 文件 每种语言的缩小选项是可定制的 打开生成的文件时显示水印 任务运行程序资源管理器集成 命令行支持 快捷更新解决方案中所有捆绑包 禁止生成输出文件 转换为 Gulp |
| 注入(Program.cs) | services.AddWebOptimizer(); app.UseWebOptimizer(); | |
| 指定捆绑的项目 | 在运行时自动缩小 css 和 js,也可以在 AddWebOptimizer 中自定义。默认情况下,生成的文件不会保存到磁盘,而是保存在缓存中。 | 手动编辑 bundleconfig.json 文件来指定需要合并和缩小的文件 |
| 功能配置 | | 在 bundleconfig.json 捆绑时设置 |
| 热重载(在开发模式中保存文件自动更新浏览器效果) | VS 安装扩展,方法:菜单 - 扩展 - 管理扩展 - 联机 搜索“Bundler & Minifier” | |
| 其它资料 | ASP.NET 官方文档 |
System.ComponentModel.Win32Exception: 拒绝访问。
[ExternalException (0x80004005): 无法执行程序。所执行的命令为 "\bin\roslyn\csc.exe" /shared /keepalive:"10" /noconfig /fullpaths @"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\8c8f68eb\880f02b5\alczcu1a.cmdline"。]解决方法:
web 部署发布时勾选“在发布期间预编译”

在“配置”中,去掉“允许更新预编辑站点”前的勾,勾选“不合并。为每个页面和控件创建单独的程序集”

首先,禁止网站下所有 .php 等文件均不允许被访问到。
在 nginx 网站配置文件中,include enable-php-**.conf; 上方插入:
location ~ ^/.*\.(php|php5|py|sh|bash|out)$ { deny all; }其中,^ 匹配开始,/.* 匹配所有目录和文件名,\.(php|php5|py|sh|bash|out) 匹配文件后缀名,$ 匹配结束。
即便如此,仍然忽略了 nginx 中 .php 文件名后加斜杠仍然能访问到的情况,譬如我们访问这个网址:
https://xoyozo.net/phpinfo.php/abc.htmlnginx 仍然运行了 phpinfo.php,给了后门可趁之机,所以改进为:
location ~ ^/.*\.(php|php5|py|sh|bash|out)(/.*)?$ { deny all; }Discuz! X3.4 需要写入权限的目录:
/自研目录/upload/
/config/
/data/
/uc_client/data/
/uc_server/data/
/source/plugin/
但,这些都不重要,我们已经禁止了所有目录的 .php 访问了。
第二步,解禁需要直接被访问到的文件路径。
Discuz! X3.4 根目录下的 .php 文件都是入口文件,需要能够被访问到:
/admin.php
/api.php
/connect.php
/forum.php
/group.php
/home.php
/index.php
/member.php
/misc.php
/plugin.php
/portal.php
/search.php其它目录中需要被直接访问到的文件:
/archiver/index.php
/m/index.php
/uc_server/admin.php
/uc_server/avatar.php
/uc_server/index.php部分插件文件需要能够被直接访问到:
/source/plugin/magmobileapi/magmobileapi.php
/source/plugin/smstong/accountinfo.php
/source/plugin/smstong/checkenv.php另外如果有自建目录需要有 .php 访问权限,那么也需要在此处加白,本文以 /_/ 目录为例
最终拼成:工具
location ~ ^(?:(?!(/admin\.php|/api\.php|/connect\.php|/forum\.php|/group\.php|/home\.php|/index\.php|/member\.php|/misc\.php|/plugin\.php|/portal\.php|/search\.php|/archiver/index\.php|/m/index\.php|/uc_server/admin\.php|/uc_server/avatar\.php|/uc_server/index\.php|/source/plugin/magmobileapi/magmobileapi\.php|/source/plugin/smstong/accountinfo\.php|/source/plugin/smstong/checkenv\.php|/_/.*\.php))/.*\.(php|php5|py|sh|bash|out)(/.*)?)$ { deny all; }这里用到正则表达式中的“不捕获”和“负向零宽断言”语法,格式为:
^(?:(?!(允许的目录或文件A|允许的目录或文件B))禁止的目录和文件)$值得注意的是,此句负向零宽断言中的匹配内容是匹配前缀的,也就是说
https://xoyozo.net/index.php
https://xoyozo.net/index.php/abc.html都可以访问到,而
https://xoyozo.net/forbidden.php
https://xoyozo.net/forbidden.php/abc.html都访问不到,这是符合需求的。
如果自建目录 /_/ 下有写入需求,单独禁止即可,以 /_/upload/ 为例:
location ~ ^/_/upload/.*\.(php|php5|py|sh|bash|out)(/.*)?$ { deny all; }ThinkPHP 网站有统一的访问入口,可按本文方法配置访问权限。
特别注意:上面的代码必须加在 PHP 引用配置(include enable-php-**.conf; 或 fastcgi_pass)的上方才有效。
本文使用 ASP.NET 6 版本 Senparc.Weixin.Sample.MP 示例项目改造。
第一步 注册多公众号
方法一:打开 appsettings.json 文件,在 SenparcWeixinSetting 节点内添加数组节点 Items,该对象类型同 SenparcWeixinSetting。
//Senparc.Weixin SDK 设置
"SenparcWeixinSetting": {
"IsDebug": true,
"Token": "",
"EncodingAESKey": "",
"WeixinAppId": "",
"WeixinAppSecret": "",
"Items": [
{
"IsDebug": true,
"Token": "a",
"EncodingAESKey": "a",
"WeixinAppId": "a",
"WeixinAppSecret": "a"
},
{
"IsDebug": true,
"Token": "b",
"EncodingAESKey": "b",
"WeixinAppId": "b",
"WeixinAppSecret": "b"
}
]
}方法二:修改 Program.cs 文件,在 UseSenparcWeixin 方法中注册多个公众号信息。
var registerService = app.UseSenparcWeixin(app.Environment,
null /* 不为 null 则覆盖 appsettings 中的 SenparcSetting 配置*/,
null /* 不为 null 则覆盖 appsettings 中的 SenparcWeixinSetting 配置*/,
register => { /* CO2NET 全局配置 */ },
(register, weixinSetting) =>
{
//注册公众号信息(可以执行多次,注册多个公众号)
//register.RegisterMpAccount(weixinSetting, "【盛派网络小助手】公众号");
foreach (var mp in 从数据库或配置文件中获取的公众号列表)
{
register.RegisterMpAccount(new SenparcWeixinSetting
{
//IsDebug = true,
WeixinAppId = mp.AppId,
WeixinAppSecret = mp.AppSecret,
Token = mp.Token,
EncodingAESKey = mp.EncodingAeskey,
}, mp.Name);
}
});完成后,我们可以从 Config.SenparcWeixinSetting.Items 获取这些信息。
第二步 接入验证与消息处理
打开 WeixinController 控制器,将构造函数改写为:
public WeixinController(IHttpContextAccessor httpContextAccessor)
{
AppId = httpContextAccessor.HttpContext!.Request.Query["appId"];
var MpSetting = Services.MPService.MpSettingByAppId(AppId);
Token = MpSetting.Token;
EncodingAESKey = MpSetting.EncodingAESKey;
}示例中 Services.MPService.MpSettingByAppId() 方法实现从 Config.SenparcWeixinSetting.Items 返回指定 appId 的公众号信息。
为使 IHttpContextAccessor 注入生效,打开 Program.cs,在行
builder.Services.AddControllersWithViews();下方插入
builder.Services.AddHttpContextAccessor();这样,我们就可以在构造函数中直接获取地址栏中的 appId 参数,找到对应的公众号进行消息处理。
第三步 消息自动回复中的 AppId
打开 CustomMessageHandler.cs,将
private string appId = Config.SenparcWeixinSetting.MpSetting.WeixinAppId;
private string appSecret = Config.SenparcWeixinSetting.MpSetting.WeixinAppSecret;替换为:
private string appId = null!;
private string appSecret = null!;并在构造函数中插入
appId = postModel.AppId;
appSecret = Services.MPService.MpSettingByAppId(postModel.AppId).WeixinAppSecret;这样,本页中使用的 appId / appSecret 会从 postModel 中获取,而非默认公众号。postModel 已在 WeixinController 中赋值当前的 appId。
改造后,我们可以在 OnTextRequestAsync() 等处理消息的方法中可以判断 appId 来处理不同的消息。
第四步 其它功能和接口
其它功能和接口均可用指定的 AppId 和对应的 AppSecret 进行调用。
项目 - 属性 - 生成 - 输出 - 文档文件,勾选“生成包含 API 文档的文件。”,“XML 文档文件路径”可留空。

在配置方法 AddSwaggerGen 中添加以下两行
var xmlFilename = $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}.xml"; options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
普通的 nginx http 反向代理 https 时是需要配置证书的,但我们又不可能由源域名的证书,所以要使用 nginx 的 stream 模块。普通的 nginx 反向代理属于第七层代理,而 stream 模块是第四层代理,通过转发的 tcp/ip 协议实现高功能,所以不需要证书。
我们这里以使用宝塔安装的 nginx 为例,其实其他系统也是类似,只要找到编译的 nginx 的源码目录就行了
编译前先将已经安装的 nginx 文件进行备份
通过 ps 命令查看 nginx 文件的路径。以下所有步骤都以自身 nginx 路径为准
# ps -elf | grep nginx
# cd /www/server/nginx/sbin/
# cp nginx nginx.bak然后查看当前 nginx 编译的参数
/www/server/nginx/sbin/nginx -V将 ./configure arguents:之后的内容复制到记事本备用(备注:我们这里其实使用的是 Tengine-2.3.1,所以下面的编译参数可能跟普通 nginx 不是很一样)
内容如下:
--user=www --group=www --prefix=/www/server/nginx --add-module=/www/server/nginx/src/ngx_devel_kit --with-openssl=/www/server/nginx/src/openssl --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --add-module=/www/server/nginx/src/lua_nginx_module --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-pcre=pcre-8.42 --with-cc-opt=-Wno-error --add-module=/www/server/nginx/src/ngx-pagespeed
进入 src 目录
cd /www/server/nginx/src我们在上面的内容中加入两个参数
./configure --user=www --group=www --prefix=/www/server/nginx --add-module=/www/server/nginx/src/ngx_devel_kit --with-openssl=/www/server/nginx/src/openssl --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --add-module=/www/server/nginx/src/lua_nginx_module --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-pcre=pcre-8.42 --with-cc-opt=-Wno-error --add-module=/www/server/nginx/src/ngx-pagespeed --with-stream --with-stream_ssl_preread_module
并执行它
然后
make && make install重启 nginx
service nginx restartnginx -V 看看模块是不是加载了

新建个站点,配置反向代理
卸载
使用 nginx.bak 文件替换掉自编译的 nginx 文件,替换后重启 nginx。
视频号直播可会生成推流地址和密钥。
微博可选“拉流”或“推流”,推/拉是针对直播平台来说的,即此处的“拉流”是指微博从视频源(如阿里云视频直播)拉流,“推流”指视频源(如 OBS)往微博推流。
微博或抖音的“拉流”方式以及 OBS 软件的使用方式请参考文章:如何使用阿里云视频直播服务在抖音上直播监控摄像头画面,建议先了解一下流程,有助于进一步配置“推流”方式。
第一步,从微博直播的“推流”方式或微信视频号的创建直播页面中生成推流地址和密钥:

第二步,配置 OBS Studio 的推流服务:

服务选择“自定义”,填入服务器和串流密钥,“应用”。

点击“开始推流”。

在微博或视频号中预览直播并继续创建完成。
