如何在Python瓶中提供带有希伯来语名称的静态文件?[英] How to serve static file with a hebrew name in python bottle?

本文是小编为大家收集整理的关于如何在Python瓶中提供带有希伯来语名称的静态文件?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我从客户端收到一个请求,从服务器下载一些文件. 文件名在希伯来语中.

@bottle.get("/download/<folder_name>/<file_name>")
def download(folder_name, file_name):

    file_name =  file_name.decode('utf-8')
    folder_name =  folder_name.decode('utf-8')

    if os.path.exists(os.path.join(folder_name, file_name)):
        return bottle.static_file(file_name, root=folder_name, download=True)

最后一行失败:

return bottle.static_file(file_name, root=folder_name, download=True)

我有一个例外:

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

我不知道我在这里做错了什么.

Callstack显示异常来自Python瓶代码:

File "C:\Python27\Lib\site-packages\bottle-0.10.9-py2.7.egg\bottle.py", line 1669, in __setitem__
  def __setitem__(self, key, value): self.dict[_hkey(key)] = [str(value)]

请帮助.

注意, omer.

推荐答案

瓶试图将HTTP响应上的Content-Disposition标题设置为attachment; filename=....这对非ASCII字符不起作用,因为Bottle在内部使用str处理HTTP标头...但是即使没有,也没有跨浏览器兼容的方法来设置Content-Disposition -ascii filename. ( background . P>

您可以将download='...'设置为仅安全的assii string,以覆盖瓶子的默认猜测(它使用的是本地文件名,包含unicode).

另外,省略了download参数,并依靠浏览器从URL末尾猜测文件名. (这是获取Unicode下载文件名的唯一广泛兼容的方法.)不幸的是,瓶子将完全省略Content-Disposition,因此请考虑更改返回响应中的标头,以包含PLAIN Content-Disposition: attachment而无需文件名.也许您不在乎,如果Content-Type是总是下载的Content-Type.

其他推荐答案

在最后一行中尝试使用utf-8编解码器编码Unicode字符串:

return bottle.static_file(file_name.encode("utf-8"), root=folder_name.encode("utf-8"), download=True)

从您提供的代码中,看起来bottle.static_file方法期望以二进制格式使用字符串,因此使用ascii cocdec进行默认转换(从错误消息中可以看到).就像在您的字符串中一样,您使用的不是ASCII的希伯来字符,默认转换失败.您需要使用支持国家字母的编解码器,例如utf-8.

有关更多信息,请参阅 python中的unicode,完全demystified

其他推荐答案

send_file参数必须是Unicode. 这是瓶子0.5.8的解决方案:

# -*- coding: utf-8 -*-
from bottle import route, run, request, send_file, WSGIRefServer
@route('/:filename#.*#')
def static_file(filename):
    send_file(filename.decode('utf-8'), root=ur'g:\Folder')
run(server=WSGIRefServer, host='192.168.1.5', port=80)  

本文地址:https://www.itbaoku.cn/post/1975370.html

问题描述

I receive a request from the client to download some file from the server. The filename is in Hebrew.

@bottle.get("/download/<folder_name>/<file_name>")
def download(folder_name, file_name):

    file_name =  file_name.decode('utf-8')
    folder_name =  folder_name.decode('utf-8')

    if os.path.exists(os.path.join(folder_name, file_name)):
        return bottle.static_file(file_name, root=folder_name, download=True)

The last line fails :

return bottle.static_file(file_name, root=folder_name, download=True)

I get an exception :

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

I have no idea what am i doing wrong here.

Callstack shows the exception derives from python bottle code:

File "C:\Python27\Lib\site-packages\bottle-0.10.9-py2.7.egg\bottle.py", line 1669, in __setitem__
  def __setitem__(self, key, value): self.dict[_hkey(key)] = [str(value)]

Please help.

Regard, Omer.

推荐答案

Bottle is trying to set the Content-Disposition header on the HTTP response to attachment; filename=.... This doesn't work for non-ASCII characters, as Bottle handles HTTP headers with str internally... but then even if it didn't, there's no cross-browser-compatible way to set a Content-Disposition with a non-ASCII filename. (Background.)

You could set download='...' to a safe ASCII-only string to override Bottle's default guess (which is using the local filename, containing Unicode).

Alternatively, omit the download argument and rely on the browser guessing the filename from the end of the URL. (This is the only widely compatible way to get a Unicode download filename.) Unfortunately then Bottle will omit Content-Disposition completely, so consider altering the headers on the returned response to include plain Content-Disposition: attachment without a filename. Or perhaps you don't care, if the Content-Type is one that will always get downloaded anyway.

其他推荐答案

In the last line try encoding the unicode string into binary using utf-8 codec:

return bottle.static_file(file_name.encode("utf-8"), root=folder_name.encode("utf-8"), download=True)

From the code you provided, it looks like the bottle.static_file method expects a string in binary format, therfore a default conversion using ascii codec is performed (as seen from the error message). As in your string you use Hebrew characters, which are not part of ascii, the default conversion fails. You need to use codec that supports national alphabets, like the utf-8.

For more information, see Unicode In Python, Completely Demystified

其他推荐答案

send_file parameters must be unicode. Here is solution for bottle 0.5.8:

# -*- coding: utf-8 -*-
from bottle import route, run, request, send_file, WSGIRefServer
@route('/:filename#.*#')
def static_file(filename):
    send_file(filename.decode('utf-8'), root=ur'g:\Folder')
run(server=WSGIRefServer, host='192.168.1.5', port=80)