Closed newdee closed 5 years ago
目前已知的问题是,无法发送文件名为中文的文件。 可能有效 的解决方案在最后。
我大致追了一下,目测是 urllib3.fields 的历史遗留 bug 引起的。
当通过 urllib3
发送 post
请求的时候,如果 post 数据中 name
或 filename
字段内容是中文,则会导致发送失败。常见的解决方法是把这个字段留空。在 itchat.components.messages
中在处理 name
字段的时候用了留空处理,但是filename
字段由于某种原因直接使用了文件名(猜测是 wx 服务器端要求使用这个字段),因此导致问题发生。稍微查了一下这个问题从 五年前 就在讨论了但是没有结果。(甚至连算不算 bug 都没有 定论 )
urllib3.fileds
的相关代码如下
def format_header_param(name, value):
"""
Helper function to format and quote a single header parameter.
Particularly useful for header parameters which might contain
non-ASCII values, like file names. This follows RFC 2231, as
suggested by RFC 2388 Section 4.4.
:param name:
The name of the parameter, a string expected to be ASCII only.
:param value:
The value of the parameter, provided as a unicode string.
"""
if not any(ch in value for ch in '"\\\r\n'):
result = '%s="%s"' % (name, value)
try:
result.encode('ascii')
except (UnicodeEncodeError, UnicodeDecodeError):
pass
else:
return result
if not six.PY3 and isinstance(value, six.text_type): # Python 2:
value = value.encode('utf-8')
value = email.utils.encode_rfc2231(value, 'utf-8') # <- bug 似乎是这里两行引起的
value = '%s*=%s' % (name, value)
return value
这里使用了 *=
是遵循 RFC 2231, chapter 4. 大致来说是表明 *=
的内容包括了 language 和 character set 两个数据。这点在刚才给出的 issue 中也提到了。但这似乎会给中文字符带来问题。我自己的情况是,把 *=
替换为 =
之后中文文件就可用了。
以下是也许有效的解决方法
执行
cd $(pip3 show urllib3|grep Location|cut -d' ' -f2)'/urllib3/'
cp fields.py fields.py.bak
sed -i 's/\*=/=/' fields.py
之后重启 EFB
PS: urllib3 在今年3月更新了这段代码。我感觉问题应该还在,但是我没测试。有兴趣的话可以从 github 更新一下试试……
最新的 urllib3 1.25.2 似乎已经修正了这个 bug。
通过更新 requests
和 urllib3
应该也可以解决。
你可以先用 pip 卸载当前的 urllib3
和 requests
然后重新安装。注意你可能需要多执行几次卸载来保证所有旧版本都被移除。
更新了最新的 urllib3 之后,tg 无法从 wx 端接收中文文件名的文件。因为 ptb 11.0 使用了自己修改过的 urllib3,而这个 urllib3 中存在这个 bug。可以选择安装如下版本来解决。
efb-qq-slave (2.0.0a5)
efb-sticker2img-middleware (0.0.1)
efb-telegram-master (2.0.0b20)
efb-wechat-slave (2.0.0a18)
ehforwarderbot (2.0.0b15)
itchat (1.3.10)
如果希望使用 ptb 11,则可以之下以下命令来解决。
cd $(pip3 show python-telegram-bot|grep Location|cut -d' ' -f2)'/telegram/vendor/ptb_urllib3/urllib3/'
sudo cp fields.py fields.py.bak
sudo sed -i 's/\*=/=/' fields.py
@catbaron0 用了这个方法之后接收到文件都会变成UTF8-xxxx这种乱码形式的名字的文件,请问这个有什么办法解决吗
@catbaron0 用了这个方法之后接收到文件都会变成UTF8-xxxx这种乱码形式的名字的文件,请问这个有什么办法解决吗
迷。以前我记得没这个问题,不知道是什么地方更新了。而且最近我应该没空追这个问题……
@catbaron0 用了这个方法之后接收到文件都会变成UTF8-xxxx这种乱码形式的名字的文件,请问这个有什么办法解决吗
迷。以前我记得没这个问题,不知道是什么地方更新了。而且最近我应该没空追这个问题……
不知道是不是这个原因引起的。之后的如果同时发送了多个文件,所有的文件都是同一个 @catbaron0 @blueset
之后的如果同时发送了多个文件,所有的文件都是同一个 @kettly1260
参见 #22。
现在不止无法发送表情了,连文件都无法发送。
尝试发送word文档失败。