Django: 使用ASCII头的Unicode文件名?

4 投票
1 回答
4080 浏览
提问于 2025-04-15 22:07

我有一堆奇怪编码的文件,比如:02 - Charlie, Woody and You/Study #22.mp3,这文件名还算可以,但有几个特殊字符在Django或者nginx这里出问题了。

>>> test = u'02 - Charlie, Woody and You/Study #22.mp3'
>>> test
u'02 - Charlie, Woody and You\uff0fStudy #22.mp3'

我用nginx作为反向代理,连接到Django自带的web服务器(现在还在开发阶段),同时用PostgreSQL作为我的数据库。我的数据库和表都是en_US.UTF-8编码,我还用pgadmin3在Django外面查看我的表。我的问题比标题说的要复杂一些,首先,我应该怎么把这些奇怪的文件名保存到数据库里呢?我现在的方法是

'path': smart_unicode(path.lstrip(MUSIC_PATH)),
'filename': smart_unicode(file)

当我打印出这些值时,它们显示为u'whateverthecrap'

我不确定这样做是否正确,但假设是这样的话,现在我在下载时遇到问题。

我的下载视图大概是这样的:

def song_download(request, song_id):
    song = get_object_or_404(Song, pk=song_id)
    url = u'/static_music/%s/%s' % (song.path, song.filename)

    print url

    response = HttpResponse()
    response['X-Accel-Redirect'] = url
    response['Content-Type'] = 'audio/mpeg'
    response['Content-Disposition'] = "attachment; filename=test.mp3"

    return response

大部分文件都能下载,但当我尝试下载02 - Charlie, Woody and You/Study #22.mp3时,Django给我返回了这个错误:'ascii' codec can't encode character u'\uff0f' in position 118: ordinal not in range(128), HTTP response headers must be in US-ASCII format

如果我的文件名超出了范围,我该如何使用一个ASCII格式的字符串呢?02 - Charlie, Woody and You\uff0fStudy #22.mp3似乎也不行……

编辑 1

我使用的是Ubuntu操作系统。

1 个回答

8

虽然 是一个不常见且不太好的字符,但你的脚本会因为任何非ASCII字符而出错。

response['X-Accel-Redirect'] = url

url 是Unicode格式(而且它不是一个网址,它是一个文件路径)。响应头是以字节形式存在的。你需要对它进行编码。

response['X-Accel-Redirect'] = url.encode('utf-8')

这假设你是在一个文件系统编码为UTF-8的服务器上运行。

(现在,如何在 Content-Disposition 头中编码文件名……这就复杂多了!)

撰写回答