【问题标题】:Python ─ UTF-8 filename from HTML form via CherryPyPython ─ 通过 CherryPy 来自 HTML 表单的 UTF-8 文件名
【发布时间】:2013-08-17 13:45:02
【问题描述】:
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 的编码或解码问题,因为上传是由它处理的,like here

它是如何工作的:
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ürfel”


  • 更改系统编码:

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

    结果:“Würfel”


  • 编码尝试1:

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

    结果:“Würfel”


  • 编码尝试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)
    

【问题讨论】:

  • 请发布repr(img_file.filename),以便我们可以在您的上下文中创建相同的字节数组
  • @PaoloCasciello, repr(img_file.filename) 回复了这个u'W\xc3\xbcrfel.jpg'

标签: python html encoding utf-8 cherrypy


【解决方案1】:

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

>>> s = u'W\xc3\xbcrfel.jpg'
>>> print s.encode('latin1')
Würfel.jpg
>>> 

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

【讨论】:

  • 谢谢。现在必须这样做。当我用 CherryPy 找到真正的解决方案时,我会在编辑中发布它。
  • @JonathanRoot 正确的 CherryPy 方法是使用 cherrypy.tools.encode/cherrypy.tools.decode&lt;meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1"&gt; 似乎告诉浏览器使用不同的编码,所以这是你被卡住的地方。
【解决方案2】:

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

【讨论】:

  • 感谢您的提示。我添加了元标记作为解决此问题的尝试。我将 UTF/8 与 ISO-8859-1 混淆了,所以我会认为这是个问题。
  • 你应该使用 Content-Type: text/html;charset=UTF-8,并且到处都一致说你的字符集是 UTF-8; ubuntu 到处都使用 UTF-8。
  • 所以当我的页面要被不同系统使用时,也许我应该把它留在代码中:reload(sys) sys.setdefaultencoding('utf-8')
  • @JonathanRoot 由于日文编码的旧 IE 安全问题,元标记被忽略。这就是为什么人们应该始终使用带有内容编码服务器响应标头的 utf8。
  • @AnttiHaapala,我开始相信 reload(sys) 只会影响我的系统,而不影响客户的系统。所以使用它会有所帮助。
猜你喜欢
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-17
  • 1970-01-01
  • 2020-09-15
相关资源
最近更新 更多