Django:带有ASCII标题的Unicode文件名?

4

我有一份奇怪编码的文件列表: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
我不确定你这里使用的斜杠字符“/”是作为文件名的一部分还是父目录加文件名的组成部分?(因为,在大多数现代文件系统中,“/”斜杠字符不能作为文件名的一部分,因为会与目录结构混淆。)尽管如此,为了以ASCII安全的方式编码斜杠,你可以使用“\u002f”...但我不建议这样做。 - ewall
这更像是一首歌曲中的分隔符,我不确定它们是如何加入的,但它并不是真正的“/”,而是一个“/”,这可能是为什么它被允许的原因。这可能是一个糟糕的例子,但它已经在许多其他Unicode字符上实现了。 - TheLizardKing
1个回答

8

尽管 是一个不常见且不希望出现的字符,但你的脚本会因为任何非ASCII字符而中断。

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

url 是 Unicode 编码(不是 URL,而是文件路径)。响应头是字节。您需要对其进行编码。

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

假设您在使用UTF-8作为文件系统编码的服务器上运行。

现在,如何在Content-Disposition头中编码文件名...这是一个更加棘手的问题!


哈哈,抱歉,url以前是一个url。我正在运行Ubuntu 10.4(Beta),有没有办法查看我的文件系统编码? - TheLizardKing
是的,除非你已经更改了它,否则Ubuntu将使用UTF-8。除Windows之外的所有现代操作系统都使用UTF-8。 - bobince
1
根据这个回答filename参数必须始终为ASCII编码,例如:filename=test.encode('ascii', 'replace'),而较新的浏览器(遵循RFC-6266)可以使用filename*,例如:filename*=''urlquote(test) - tutuDajuju

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接