Django:在自定义URL后提供媒体
我当然知道,通过Django提供静态文件是个大忌,但我对如何用自定义网址来隐藏文件的真实位置感到困惑。之前有个帖子提到过这个问题,虽然我接受的答案似乎是个“错误”的做法。
这是我的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
这个解决方案看起来非常好,但实际上并不够完美。我该如何避免直接链接到mp3文件,同时又能通过nginx或apache来提供服务呢?
编辑 1 - 额外信息
目前我可以通过这样的地址获取我的文件:
http://www.example.com/music/song/1692/download/
但上面提到的方法简直就是在自找麻烦。
我该如何在保持上面功能的同时,让nginx或apache来提供媒体文件呢?这是不是应该在web服务器层面上解决?需要一些复杂的mod_rewrite吗?
http://static.example.com/music/Aphex%20Twin%20-%20Richard%20D.%20James%20(V0)/10%20Logon-Rock%20Witch.mp3
编辑 2 - 更多额外信息
我使用nginx作为前端,并通过反向代理连接到apache开发服务器,所以如果确实需要一些mod_rewrite的工作,我需要找到适合nginx的解决方案。
3 个回答
基本的想法是让你的Django视图跳转到一个安全的网址,这个网址是由你的媒体服务器提供的。
可以参考Graham Dumpleton(mod_wsgi的作者)提供的建议列表。
为了更好地理解之前的回答,你可以修改下面的代码,让nginx直接提供你的下载文件,同时又能保护这些文件不被随意访问。
首先,在你的nginx.conf文件中添加一个类似这样的位置:
location /files/ {
alias /true/path/to/mp3/files/;
internal;
}
这个内部设置会让文件不被直接访问。接下来,你需要一个像这样的Django视图:
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处理。