Django:在通用视图中提供下载
我想从一个文件夹里提供几个mp3文件,文件夹路径是/home/username/music
。我本以为这没什么大不了的,但现在对如何使用通用视图和我自己的网址有点困惑。
这是我的urls.py文件:
url(r'^song/(?P<song_id>\d+)/download/$', song_download, name='song_download'),
我参考的例子在Django文档的通用视图部分可以找到:http://docs.djangoproject.com/en/dev/topics/generic-views/(在最底部)
我不太确定如何根据我的需求进行调整。以下是我的views.py文件:
def song_download(request, song_id):
song = Song.objects.get(id=song_id)
response = object_detail(
request,
object_id = song_id,
mimetype = "audio/mpeg",
)
response['Content-Disposition'= "attachment; filename=%s - %s.mp3" % (song.artist, song.title)
return response
我其实不知道怎么让它输出我的mp3文件,而不是现在这样输出一个包含当前页面HTML内容的.mp3文件。我的模板应该是我的mp3文件吗?我需要设置Apache来提供这些文件,还是Django可以从文件系统中获取mp3文件(当然需要正确的权限)并提供呢?如果确实需要配置Apache,我该怎么告诉Django呢?
提前谢谢你。这些文件都在硬盘上,所以我不需要即时“生成”任何东西,我也希望尽量不暴露这些文件的位置。如果能有一个简单的/song/1234/download就太好了。
4 个回答
用Django来提供静态文件并不是个好主意,建议使用Apache、nginx等服务器。
https://docs.djangoproject.com/en/dev/howto/static-files/deployment/
为了把我对Tomasz Zielinski的评论变成一个真正的回答:
有几个原因,确实让apache/nginx等服务器来处理文件传输会更好。大多数服务器都有一些机制来帮助处理这种情况:Apache和lighttpd有xsendfile,nginx有X-Accel-Redirect。
这个想法是,你可以使用django的所有功能,比如漂亮的网址、认证方法等等,但让服务器来负责发送文件。你的django视图需要做的,就是返回一个带有特殊头部的响应。然后服务器会用实际的文件替换这个响应。
以下是apache的示例:
def song_download(request):
path = '/path/to/file.mp3'
response = HttpResponse()
response['X-Sendfile'] = smart_str(path)
response['Content-Type'] = "audio/mpeg"
response['Content-Length'] = os.stat(path).st_size
return response
- 安装 mode_xsendfile
- 在你的apache配置中添加
XSendFileOn on
和(根据版本不同)XSendFileAllowAbove on
或XSendFilePath the/path/to/serve/from
。
这样你就不会暴露文件的位置,同时可以把所有的网址管理都留给django处理。
你为什么想用通用视图来做这个呢?其实不用通用视图也很简单:
from django.http import HttpResponse
def song_download(request, song_id):
song = Song.objects.get(id=song_id)
fsock = open('/path/to/file.mp3', 'rb')
response = HttpResponse(fsock, content_type='audio/mpeg')
response['Content-Disposition'] = "attachment; filename=%s - %s.mp3" % \
(song.artist, song.title)
return response
我不太确定用通用视图是否能实现这个功能。不过无论如何,在这里使用通用视图都是多余的。因为没有模板可以渲染,通用视图自动提供的上下文就没什么用处了。