Python ─ 来自 HTML 表单的 UTF-8 文件名,通过 CherryPy


Python Header:      # ! /usr/bin/env python
                    # -*- coding: utf-8 -*-
                    # image_upload.py
Cherrypy Config:    cherrypy.config.update(
                        {'tools.encode.on': True,
                         'tools.encode.encoding': 'utf-8',
                         'tools.decode.on': True,
                        },)
HTML Header:        <head><meta http-equiv="Content-Type"
                    content="text/html;charset=ISO-8859-1"></head>
""" Python        2.7.3
    Cherrypy      3.2.2
    Ubuntu        12.04
"""

使用 HTML 表单,我正在将图像文件上传到数据库。到目前为止,这没有问题。但是,如果文件名不是 ASCII 中的 100%,则似乎无法以 UTF-8 格式检索它。这很奇怪,因为使用 HTML 文本输入字段,从保存到显示,它都可以毫无问题地工作。因此,我认为这是Web应用程序框架CherryPy的编码或解码问题,因为上传是由它处理的,就像这里一样。

工作原理:
HTML 表单将上传的文件 POST 到另一个 Python 函数,该函数在标准字典**kwargs中接收文件。从这里您可以获得带有扩展名的文件名,如下所示:filename = kwargs['file'].filename .但这已经是错误的编码了。到目前为止,图像尚未以任何方式进行处理、存储或使用。

我要求一个解决方案,可以防止它,只是解析文件名并将其"手动"更改回来。我想结果已经是 UTF-8,这使得正确处理起来很麻烦。这就是为什么让CherryPy这样做可能是最好的方法。但也许这甚至是一个 HTML 问题,因为文件来自表单。

这是错误的解码变音符号。
我需要的是作为结果的输入。

input → result        input → result  
  ä   →   ä            Ä   →   Ä  
  ö   →   ö            Ö   →   Ö 
  ü   →   ü            Ü   →   Ãœ  

以下是获得正确结果的失败尝试,即:"Würfel">
注:img_file = kwargs['file']


  • 原始尝试:

    result = img_file.filename.rsplit('.',1)[0]
    

    结果:"WÃ1/4rfel"


  • 更改系统编码:

    reload(sys)
    sys.setdefaultencoding('utf-8')
    

    结果:"WÃ1/4rfel"


  • 编码尝试 1:

    result = img_file.filename.rsplit('.',1)[0].encode('utf-8')
    

    结果:"WÃ1/4rfel"


  • 编码尝试 2:

    result = unicode(img_file.filename.rsplit('.',1)[0], 'urf-8')
    

    错误信息:

    TypeError: decoding Unicode is not supported
    

  • 解码尝试:

    result = img_file.filename.rsplit('.',1)[0].decode('utf-8')
    

    错误信息:

    UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-2: ordinal not in range(128)
    

  • 施法尝试:

    result = str(img_file.filename.rsplit('.',1)[0])
    

    错误信息:

    UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-2: ordinal not in range(128)
    

尝试使用您的字符串,似乎我可以使用 latin1 编码获取文件名。

>>> s = u'Wxc3xbcrfel.jpg'
>>> print s.encode('latin1')
Würfel.jpg
>>> 

您只需要在拆分之前使用该.encode('latin1')。但这里的问题更广泛。您真的需要弄清楚为什么您的网络编码是latin1而不是utf8。我不知道 cherrypy,但尽量确保使用 utf8,否则在通过 apache 或 nginx 等网络服务器提供应用程序时可能会出现其他故障。

问题是您使用字符集 ISO-8859-1 提供 HTML; 这使浏览器感到困惑,它们在发送到服务器时也使用字符集。始终使用 UTF-8 提供所有 HTML,使用 UTF-8 代码,并将终端设置为 UTF-8,您应该不会有问题。

相关内容

最新更新