使用pycurl从西里尔路径上传文件
我最近设计了一个上传对话框,使用的是PyCURL,这个对话框我在几个应用程序中都用到了。
我在设置pycurl的HTTPPOST选项时遇到了问题。我是这样设置的:
self.curl.setopt(self.curl.HTTPPOST, [(field, (self.curl.FORM_FILE, filename))])
如果filename是字符串,那一切都没问题。但是如果我传入的是unicode,就会出现类型错误(TypeError)。
有没有办法让我使用西里尔字母的路径呢?我尝试过用UTF-8编码,但没有成功。
谢谢你的时间。
更新:
其实我从WX控件中获取filename,所以在我处理之前它就是unicode格式。当我把它编码成UTF-8时(使用filename = filename.encode('UTF-8')),setopt设置是没问题的,但在执行时就出错了:
* About to connect() to example.com port 80 (#0)
* Trying 123.123.123.123... * connected
* Connected to example.com (123.123.123.123) port 80 (#0)
* failed creating formpost data
* Connection #0 to host example.com left intact
Traceback (most recent call last):
File "c:\python27\lib\site-packages\transfer_dialogs-0.28-py2.7.egg\transfer_dialogs\transfer_dialogs.py", line 64, in perform_transfer
self.curl.perform()
error: (26, 'failed creating formpost data')
更新2:
根据要求,提供更多信息。filename包含的是从打开对话框中获取的GetValue()结果。
logging.debug("Filename: %r encoded filename: %r" % (filename, filename.encode('UTF-8')))
结果是:
Sat Feb 05, 2011 03:33:56 core.dialogs.upload_audio DEBUG: Filename: u'C:\Users\Q\test\\u0422\u0435\u0441\u0442\u043e\u0432\u0430\u044f \u043f\u0430\u043f\u043a\u0430\test.mp3' encoded filename: 'C:\Users\Q\test\\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82\xd0\xbe\xd0\xb2\xd0\xb0\xd1\x8f \xd0\xbf\xd0\xb0\xd0\xbf\xd0\xba\xd0\xb0\test.mp3'
2 个回答
把这个问题分成两个部分来解决:
- 告诉pycurl要打开哪个文件来读取文件数据
- 把文件名以正确的编码发送到服务器
这两个编码可能相同,也可能不同。
对于第一部分,可以使用 sys.getfilesystemencoding()
来把你在Python代码中使用的Unicode文件名(这个文件名是正确的)转换成一个字符串,这样pycurl/libcurl就能用 fopen()
正确打开它。你可以使用 strace
(在Linux上)或者相应的工具来检查pycurl是否打开了正确的文件路径,Windows和Mac上也有类似的工具。
如果这个方法完全失败,你还可以通过 pycurl.READFUNCTION
从Python直接传输文件数据流。
对于第二部分,了解文件上传时文件名是如何传输的,这里有个例子。我没有找到很好的链接,但我知道这个过程并不简单,特别是当文件名非常长的时候。
文件名应该使用UTF-8编码,并且你上传的主机也要支持UTF-8文件名。如果主机支持其他非Unicode的编码方式,可以尝试用KOI8-R或WIN1251来编码文件名(不过这样做其实不太好,也不符合标准)。
补充说明,看到评论后:可能应该用 ur"C:\Users\Q\test\Тестовая папка\test.mp3".encode("UTF-8")
。这里的 u
是很重要的;如果没有它,西里尔字母会按照你控制台的编码来处理。我刚试了一下,这样做是有效的(不是上传,只是 setopt
)。