Django:在自定义URL后面提供媒体服务

时间:2010-04-22 02:53:36

标签: python django url-rewriting nginx

所以我当然知道通过Django提供静态文件会让你直接陷入地狱但我对如何使用自定义网址使用Django掩盖文件的真实位置感到困惑。 Django: Serving a Download in a Generic View但我接受的答案似乎是“错误的”做事方式。

urls.py:

url(r'^song/(?P<song_id>\d+)/download/$', song_download, name='song_download'),

views.py:

def song_download(request, song_id):
    song = Song.objects.get(id=song_id)
    fsock = open(os.path.join(song.path, song.filename))

    response = HttpResponse(fsock, mimetype='audio/mpeg')
    response['Content-Disposition'] = "attachment; filename=%s - %s.mp3" % (song.artist, song.title)

    return response

此解决方案完美地,但结果并不完美。如何在仍然通过nginx / apache服务时避免直接链接到mp3?

编辑1 - 附加信息

目前,我可以使用以下地址获取我的文件: http://www.example.com/music/song/1692/download/ 但上面提到的方法是魔鬼的工作。

如果仍然让nginx / apache为媒体提供服务,我怎样才能完成上面的工作?这是应该在网络服务器级别完成的吗?有些疯狂的mod_rewrite?

http://static.example.com/music/Aphex%20Twin%20-%20Richard%20D.%20James%20(V0)/10%20Logon-Rock%20Witch.mp3

编辑2 - 其他附加信息

我使用nginx作为我的前端和反向代理支持apache / development server所以我认为如果它确实需要某种mod_rewrite工作,我将不得不找到适合nginx的东西。

3 个答案:

答案 0 :(得分:18)

要扩展之前的答案,您应该能够修改以下代码并让nginx直接为您的下载文件提供服务,同时仍然保护文件。

首先添加一个位置,例如:

location /files/ {
   alias /true/path/to/mp3/files/;
   internal;
}

到你的nginx.conf文件(内部使得这不能直接访问)。然后你需要一个像这样的Django View:

def song_download(request, song_id):
    try:
        song = Song.objects.get(id=song_id)
        response = HttpResponse()
        response['Content-Type'] = 'application/mp3'
        response['X-Accel-Redirect'] = '/files/' + song.filename
        response['Content-Disposition'] = 'attachment;filename=' + song.filename
    except Exception:
        raise Http404
    return response

将把文件下载交给nginx。

答案 1 :(得分:3)

基本思路是让您的Django视图重定向到您的媒体服务器提供的安全URL。

请参阅mod_wsgi的作者Graham Dumpleton提出的this list

答案 2 :(得分:1)

httpdNginx都可以指定通过标头投放的静态文件。确切的标题会有所不同,因此最好在设置中添加一些内容来选择方法。