今天是值得纪念的日子,之前拍的一张图片被出版社选用,新书出版发行后赠予本人一本。今日上午收到包裹,很厚的一本书,精美的铜版纸印刷,非常精美,感谢你们!

这本书的名字叫:《物見:四十八位物件的閱讀者,與他們所見的世界》
出版物·书籍·物见·物見:四十八位物件的閱讀者,與他們所見的世界

《物见》是在近三年疫情中完成的一部文集。它由中研院近史所副研究员赖毓芝以及卫城总编辑张惠菁共同策画,邀集世界各地的东亚艺术史研究者、博物馆员、考古学家等分享一则与艺术藏品有关的轶事,当中不只描写关于他们亲近艺术品的时刻,还有将艺术品当作物件看待时,他们如何察觉到,此举隐约触及了物的使用、旅行、流传以及保存的不确定过去。

这里描述的是通过 Windows 环境搭建的 FTP 文件服务器提供音乐服务,并利用 foobar2000 APP 播放 FTP 音乐的行为。如果你对收集音乐感兴趣,或者你对无损音乐感兴趣,又有一个庞大的私有曲库,这里讲述的可能对你会有帮助。

使用 FileZilla Server 搭建 FTP 服务

下载 FileZilla Server 程序

点此进入 FileZilla Server 下载页面下载 FileZilla Server 服务端程序。

安装 FileZilla Server

安装时会提示配置管理员端口和密码,配置好管理员端口和密码,next>>直到完成安装(后续步骤建议保持默认配置,记住安装路径,后续配置 Windows 防火墙时要用)。
配置 FileZilla Server

配置 FileZilla Server

安装好会进入下方这个界面,点 Connect to FileZilla FTP Server 进入管理员登陆对话框,输入刚刚配置的管理员密码,勾上下方的 Automatically connect to this server at startup,点 OK 进入 FileZilla Server 主界面。
配置 FileZilla Server

依次点 FileZilla Server 主界面的 Server - Configure 进入配置窗口,按下图配置 ftp 服务。
配置 FileZilla Server

  1. 展开窗口左侧的 Rights management,找到 Users,点开
  2. 点右侧的 ADD
  3. 上方输入用户名:匿名登陆,这里用户名输入anonymous(如果想让用户通过用户名密码登陆,请输入你自己的用户名)
  4. Credentials 选项用户指定认证方式:匿名登陆,选择Do not require a password to log in(如果想让用户通过用户名密码登陆,请选Require a password to log in
  5. 点 Mount points 下的 ADD
  6. Native path:输入你本地电脑中作为 ftp 服务目录允许当前用户访问的目录径路:如想让当前用户有权限访问 D盘下的 ftp 文件夹下的 m 文件夹,则这里输入D:\ftp\m

    Virtual path:输入/(Virtual path 用于把 Native path 中的路径映射为 ftp 服务目录的一个虚拟路径,输入/是将它作为 ftp 服务的根目录)

  7. 右侧 Permissions 中 Access mode 用于指定当前用户对上一步的 Native path 中指定的目录的访问权限,这里设置只读权限,选择Read only,并勾选Apply permissions to subdirectories对子目录也应用只读权限;
  8. 最后,点 Apply 让上述配置生效,到此,已搭好 FTP 服务器了。

如果有多个目录需要指定为当前用户,比如 除了 D:\ftp\m,还想让当前用户有权限访问 E 盘下的 abc 文件夹,并希望将这个 abc 文件夹映射为 ftp 根目录下的 music 目录,则请重复步骤5-7,其中 Native path 添加E:\abc,Virtual path 添加/music,这样设置完成后当前用户就有登陆 ftp 时根目录是 D:\ftp\m 文件夹的内容,并同时包含一个名为 music 实则指向 E:\abc 的目录。

配置 Windows 防火墙

在访问上述步骤搭建的 FTP 对外提供服务前,还有最后一个步骤:配置 Windows 防火墙。

  1. 打开控制面板中的 Windows Defender 防火墙,点左侧的允许应用或功能通过 Windows Defender 防火墙打开允许的应用窗口
  2. 依次点更改设置(N)-允许其它应用(R)...打开添加应用窗口
  3. 点下方的浏览(B)...找到 FileZilla Server 安装目录下的启动文件 filezilla-server 选中点打开(O),回到添加应用窗口
  4. 添加,回到允许的应用窗口(根据需要勾选这里的网络类型(专用或公用)),最后,点确定完成配置。
    防火墙配置 FileZilla Server
  5. 此时,查看你本地的 ip 地址,通过这个 ip 地址即可访问上述 ftp 服务了。

配置 foobar2000 播放器,让 foobar2000 播放 ftp 服务提供的音乐

  1. iOS 上安装 foobar2000 APP;
  2. 打开 foobar2000 APP,主界面点开Media Services
    foobar2000 APP 配置项
  3. Add new,上方会出现一个文件夹图标将图标后的改成 ftp 地址,上述步骤配置的匿名访问,这里输入ftp://192.168.1.99(如果 ftp 配置为匿名访问,则这里输入 ftp://ip地址,如果需要用户名密码访问这里应该配置为 ftp://用户名:密码@ip地址)
    foobar2000 APP 配置项
  4. 设置好上一步的 ftp 地址,记录会保留在这里,点 ftp 地址即可进入 FTP 目录看到目录下的音乐文件。
    foobar2000 APP 网络音乐列表

设置封面图片

设置封面图片很简单,只需在目录中放置一张名为Folder的图片,foobar2000 在播放该目录中的音乐时就能识别并展示放置其中的封面图片。
foobar2000 APP 网络音乐列表

查看指定文件在指定时间段内的提交记录

以查询根目录下的 footer.php 文件最近三周的提交记录为例:执行 git log 命令共查到3条提交记录,其中95c2ab7是接下来要恢复到的提交:

git log --pretty=format:"%h, %cn, %cd, %s" --since='3 week ago' --before='today' --date=iso -- footer.php

执行上述命令得到的查询结果:

444ed06, Wang, 2022-09-12 20:18:53 +0800, 第三次提交的提交说明
95c2ab7, Wang, 2022-09-04 21:22:13 +0800, 第二次提交的提交说明
55d3b92, Wang, 2022-09-01 10:52:09 +0800, 第一次提交的提交说明

注意,指定的文件名前一定要有--以隔开文件名和前面的参数
%h是简写的提交记录SHA-1(需要完整形式的SHA-1请替换为%H
%cn是提交者姓名
%cd是提交时间,它的时间格式可以通过后面的--date=iso指定格式
%s是提交说明
--since--before分别指定开始和结束日期范围

恢复指定文件到指定提交

接下来的 git reset 命令用来将 footer.php 恢复到95c2ab7这次提交

git reset 95c2ab7 footer.php

如果使用 sourcetree,现在在工作台的已暂存文件中看到的就是95c2ab7这次提交时 footer.php 的样子,此时,若是提交,将恢复到历史版本(在提交前,如果你改变主意了,直接取消暂存即可)。

prismjs 是一个语法高亮工具,当需要在日志中贴上一些代码块时它会对读者阅读这些代码非常友好。最近给博客引入了 prismjs,发现对于异步载入的内容无法高亮显示,花了点事间弄清楚了原因:由于 prismjs 只在 html 页面载入时运行,那些通过类似 infinite ajax scroll 异步载入的内容则超出了它的控制范围,这就导致了异步载入的代码块无法高亮显示。

对于以上问题,prismjs 提供了三个方法作为解决方案供用户选择:Prism.highlightAll()Prism.highlightElement()Prism.highlightAllUnder()。同时,infinite ajax scroll 也提供了一些有用的与页面载入有关的事件,可以利用其中的appendednexted事件来执行 prismjs 提供的方法,以便使异步载入的代码块高亮显示。
appended事件为例,它的代码将是类似这样的:

ias.on('appended', function () {
	Prism.highlightAll();	
});

区别

Prism.highlightElement()用于直接处理包含.language-***的元素,以便高亮显示其中的代码。

Prism.highlightAll()Prism.highlightAllUnder()两者的作用仅限于查找目标元素下所有包含.language-***样式的元素,区别是查找范围不同,前者查找整个 DOM 文档,后者需要指定一个具体的目标元素,在这两个方法内部,最终都会将找到的元素交给Prism.highlightElement()逐个处理。

参考:
Prism.highlightAll()
Prism.highlightElement()
Prism.highlightAllUnder()
infinite ajax scroll appended 事件
infinite ajax scroll nexted 事件

本篇不涉及表的各种连接关联关系,仅仅记录关联的几种写法。

创建表

学校表

CREATE TABLE school (
school_id integer NOT NULL,
school_code varchar(10),
school_name varchar(50)
);

班级表

CREATE TABLE class (
class_id integer NOT NULL,
class_grade varchar(10),
class_class varchar(10),
school_id integer NOT NULL
);

学生表

CREATE TABLE student (
student_id integer NOT NULL,
student_code varchar(10),
student_name varchar(10),
class_id integer NOT NULL
);

写数据

学校表

INSERT INTO school (school_id, school_code, school_name)
VALUES
(1, 'A001', '理想中学'),
(2, 'A002', '红旗试验中学'),
(3, 'A003', '外国语学校')

班级表

INSERT INTO class (class_id, class_grade, class_class, school_id)
VALUES
(1, '2', '1', 1),
(2, '2', '2', 1),
(3, '2', '1', 2),
(4, '1', '1', 2),
(5, '3', '1', 3)

学生表

INSERT INTO student ("student_id", "student_code", "student_name", "class_id")
VALUES
(1, '1', '石头', 1),
(2, '2', '王强', 1),
(3, '3', '张建国', 1),
(4, '1', '李国华', 2),
(5, '1', '赵铁', 3),
(6, '2', '高亮', 4)

第一种写法

SELECT
a.school_id,
a.school_code,
a.school_name,
b.class_grade,
b.class_class,
c.student_code,
c.student_name
FROM
school a,
class b,
student c
WHERE
a.school_id = b.school_id
AND b.class_id = c.class_id

以上写法所有的表都被放在from关键字后面,实现的是三个表的innner jion查询关系,关联条件写在where子句里,当表多的时候逻辑混杂,不便阅读和理解。
这种写法不应该被推荐的原因,还在于它所能实现的关联关系少之又少,但也不是一无是处。(有些数据库通过*==*在这种写法上能够实现left joinright join关系)

第二种写法

SELECT
a.school_id,
a.school_code,
a.school_name,
b.class_grade,
b.class_class,
c.student_code,
c.student_name
FROM school a
INNER JOIN class b ON a.school_id = b.school_id
INNER JOIN student c ON b.class_id = c.class_id

第三种写法

SELECT
a.school_id,
a.school_code,
a.school_name,
b.class_grade,
b.class_class,
c.student_code,
c.student_name
FROM
(
( school a INNER JOIN class b ON ( a.school_id = b.school_id ) )
INNER JOIN student c ON ( b.class_id = c.class_id )
)