Django:在通用视图中提供下载

时间:2010-04-21 08:31:17

标签: python django file

所以我想从/home/username/music的文件夹中提供几个mp3。我不认为这会是一个大问题,但我对如何使用通用视图和我自己的网址有点困惑。

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/(一直在底部)

我不是100%肯定如何根据我的需要定制它。这是我的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而不是它现在做的是输出.mp3与所有当前页面html包含。我的模板应该是我的mp3吗?我是否需要设置apache来提供文件,或者Django是否能够从文件系统中检索mp3(当然是适当的权限)并提供服务?如果确实需要配置Apache,我该如何告诉Django?

提前致谢。这些文件都在HD上,所以我不需要在现场“生成”任何东西,我想尽可能防止泄露这些文件的位置。一个简单/歌曲/ 1234 /下载将是太棒了。

3 个答案:

答案 0 :(得分:15)

为什么要使用通用视图执行此操作?没有通用视图,这很容易做到:

from django.http import HttpResponse


def song_download(request, song_id):
    song = Song.objects.get(id=song_id)
    fsock = open('/path/to/file.mp3', 'r')
    response = HttpResponse(fsock, content_type='audio/mpeg')
    response['Content-Disposition'] = "attachment; filename=%s - %s.mp3" % \
                                     (song.artist, song.title)
    return response

我不确定是否可以通过一般视图以某种方式使这项工作成为可能。但不管怎样,使用一个在这里是多余的。没有要渲染的模板,通用视图自动提供的上下文是无用的。

答案 1 :(得分:7)

将我对Tomasz Zielinski的评论包装成一个真实的答案:

出于几个原因,让apache / nginx / etc执行发送文件的工作确实更好。 大多数服务器都有这种用例的机制:Apache和lighttpd都有xsendfile,nginx有X-Accel-Redirect。

这个想法是你可以使用django的所有功能,如漂亮的URL,验证方法等,但让服务器完成提供文件的工作。您的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 onXSendFilePath the/path/to/serve/from

这样您就不会透露文件位置,并将所有网址管理保留在django中。

答案 2 :(得分:1)

使用Django提供静态文件是一个坏主意,使用Apache,nginx等。

https://docs.djangoproject.com/en/dev/howto/static-files/deployment/