最近在自己的Ubuntu上学着用pyftpdlib库写了一个ftp服务器,具体内容官方文档已经写得非常详细了,例子也很丰富,好心人也有中文的教程,就不多说了(关键是官方文档很短,不像有些文档,写得详细得来根本看不到尽头)
这里需要补充的一点就是关于中文乱码的问题。我的客户端是win10 + FlashFXP 和 LeapFTP 两个ftp客户端,FlashFXP没有乱码,但是LeapFTP全是乱码
研究了多久,发现是这个原因:
字符在网络传输过程中的编码解码问题:
pyftpdlib的代码里发送和接收文件名是用utf-8
在编码解码,FlashFXP也是用的utf-8
编码解码,但是LeapFTP是用的gbk
在编码和解码,编码方式不一样就会导致服务器发来的数据我们看不懂,客户端发去的数据服务器不认识,例如〔没有这个文件或文件夹〕这类错误
解决办法是:
①让两者的编码方式一致;②或者文件名、文件夹名全部用英文字母+数字
解决方案一:关闭客户端的utf8
主要是针对LeapFTP的,其他客户端应该在设置里面有。
在 LeapFTP 的界面里,按快捷方式Ctrl+r
调出运行命令的对话框,输入OPTS UTF8 OFF
,然后选中下面有个刷新的,确定,就可以了。如果解决不到,就需要下面解决方案二:修改源代码了
我觉得解决不到...
解决方案二:用FlashFXP!
靠谱
解决方案三:修改pyftpdlib的源代码
当然,源代码是用py写的
这样处理主要原理是:pyftpdlib是把汉字文件名用utf-8编码然后发送到fto客户端的,但是很多windows上的ftp客户端对收到的文件名编码后又是用gbk在解码,结果就biang了三,相当于鸡同鸭讲;然后客户端用gbk编码后发送给服务器(比如要打开一个中文名文件夹),服务器又瓜不兮兮的用utf-8解码,当然就not such files or director了。处理的办法就是依着客户端的编码格式来,因为客户端源代码已经被编译了改不了,只有改pyftpdlib的源码了,那是明文写的可以随便改。
- 找到pyftpdlib的模块(文件夹)
如果是全局安装的,就上网搜一下吧。我是虚拟py环境安装的,pyftpdlib(1.5.6)
模块的位置是:
你的app/venv/lib/python3.6/site-packages/pyftpdlib
-rw-rw-r-- 1 xqq xqq 35K 12月 30 2017 authorizers.py
-rw-rw-r-- 1 xqq xqq 774 10月 24 16:26 _compat.py
-rw-rw-r-- 1 xqq xqq 25K 4月 20 23:51 filesystems.py
-rw-rw-r-- 1 xqq xqq 25K 4月 20 23:49 filesystems.py.ori
-rw-rw-r-- 1 xqq xqq 142K 4月 20 23:55 handlers.py
-rw-rw-r-- 1 xqq xqq 142K 4月 20 21:43 handlers.py.ori
-rw-rw-r-- 1 xqq xqq 2.8K 10月 24 16:28 __init__.py
-rw-rw-r-- 1 xqq xqq 36K 12月 30 2017 ioloop.py
-rw-rw-r-- 1 xqq xqq 5.7K 10月 24 16:26 log.py
-rw-rw-r-- 1 xqq xqq 4.8K 4月 26 2018 __main__.py
-rw-rw-r-- 1 xqq xqq 3.8K 10月 24 16:26 prefork.py
drwxrwxr-x 2 xqq xqq 4.0K 4月 20 23:56 __pycache__
-rw-rw-r-- 1 xqq xqq 22K 10月 24 16:26 servers.py
drwxrwxr-x 3 xqq xqq 4.0K 4月 20 15:44 test
需要修改的是这两个文件,后面加ori的是我在修改前备份的文件,是人家原版(就是编码解码都是用背时utf-8写的那个)
-rw-rw-r-- 1 xqq xqq 25K 4月 20 23:51 filesystems.py
-rw-rw-r-- 1 xqq xqq 25K 4月 20 23:49 filesystems.py.ori
-rw-rw-r-- 1 xqq xqq 142K 4月 20 23:55 handlers.py
-rw-rw-r-- 1 xqq xqq 142K 4月 20 21:43 handlers.py.ori
用vim
打开这两个文件修改,用/encode
和/decode
查找进行编码和解码的代码,把后面的参数里的'utf-8'
通通改成'gbk'
。encode大概是为了编码后传到我们ftp客户端上来,decode大概是从我们ftp客户端回传回服务器的。我的修改了这些:
# filesystems.py
# 503
yield line.encode('utf8', self.cmd_channel.unicode_errors)
# 635
yield line.encode('utf8', self.cmd_channel.unicode_errors)
# handlers.py
# 1413
return bytes.decode('utf8', self.unicode_errors)
# 1746
asynchat.async_chat.push(self, s.encode('utf8'))
# 2211
data = data.encode('utf8', self.unicode_errors)
# 2238
data = data.decode('utf8', self.unicode_errors)
# 2555
home = home.decode('utf8')
可能会用到的vim命令:
258 gg
:直接跳到258行去
/encode
:查找encode字符串 →enter
→n
R
:改写
:wq
:保存并退出
其他vim命令请看:win速查表
修改好以后,LeapFTP就正常了,因为两段的编码方式都改成了gbk
。
网友评论