Apache与Django中的XsendFile

7 投票
2 回答
3812 浏览
提问于 2025-04-18 12:29

我在用Apache通过虚拟主机(Vhost)来运行我的Django项目。我的配置文件如下:

WSGIPythonPath /srv/www/myproject/testproject/


<VirtualHost *:80>
    ServerAdmin admin@betarhombus.com
    ServerName www.betarhombus.com
    WSGIScriptAlias / /srv/www/testproject/testproject/testproject/wsgi.py
    <Directory /srv/www/testproject/testproject/testproject>
        <Files wsgi.py>
            Require all granted
        </Files>
    </Directory>
    Alias /static/ /srv/www/testproject/testproject/static/
    Alias /media/  /srv/www/testproject/testproject/media/

    <Directory /srv/www/testproject/testproject/static>
        Require all granted
    </Directory>
    <Directory /srv/www/testproject/testproject/media>
        Require all granted
    </Directory>

</VirtualHost>

我想限制媒体文件只能被特定的登录用户访问。所以我遇到了XsendFile。如果我理解得没错,它的作用是让Django负责检查你想提供的媒体文件的权限,然后由Apache作为静态文件来提供这些文件。根据我的猜测,整个过程是这样的:

  1. 激活XsendFile。
  2. 创建一个视图,用来检查媒体文件的权限等,并提供这些文件。
  3. 在urls.py文件中将其与URL关联。

这样我就可以使用`,并且它的工作方式就像是通过最初的媒体文件URL提供的一样。我理解得对吗?我有以下几个问题:

关于1. 激活XSendFile。这应该在我的Vhost标签内的配置文件中完成吗?只设置XsendFile就够了吗?我需要删除媒体指令的Alias和媒体文件的相关部分吗?我希望媒体文件只通过我的视图来提供。

还有其他我需要注意的事项吗?

编辑:我的设置是:

 <VirtualHost *:80>
    ServerAdmin admin@betarhombus.com
    ServerName www.betarhombus.com
    WSGIScriptAlias / /srv/www/testproject/testproject/testproject/wsgi.py
    XSendFile On
    XsendFilePath /srv/www/testproject/testproject/media/
    <Directory /srv/www/testproject/testproject/testproject>
        <Files wsgi.py>
            Require all granted
        </Files>
    </Directory>
    Alias /static/ /srv/www/testproject/testproject/static/
    <Directory /srv/www/testproject/testproject/static>
        Require all granted
    </Directory>
</VirtualHost>

我的urls.py:

#for xsendmedia file serving
url(r'^media\/(?P<path>.*)$', 'customer.views.media_xsendfile'),

还有我的视图:

def media_xsendfile(request, path):  
    #here will be checked if user can access media
    response = HttpResponse()
    response['Content-Type']=''
    response['X-Sendfile']= smart_str(os.path.join(settings.MEDIA_ROOT, path))
    return response

我的问题是,有些媒体文件可以正常共享,而有些则不行,出现了内部服务器错误。

2 个回答

1

如果有人在使用更新版本的Apache(2.4)时遇到同样的问题,这里是我最终让它工作的办法:

<VirtualHost *:80>
        XSendFile on
        
        Alias /static/ /mnt/mysite/static/
        Alias /media/ /mnt/mysite/media/

        <Directory /mnt/mysite/static>
                Require all granted
        </Directory>

        <Directory /mnt/mysite/media>
                Require all granted
        </Directory>

        <Directory /mnt/mysite/media/protected>
                Require all denied
        </Directory>
        XSendFilePath /mnt/mysite/media/protected

        <Directory /home/benbb96/mysite>
                <Files wsgi.py>
                        Require all granted
                </Files>
        </Directory>

        WSGIDaemonProcess mysite python-home=/home/benbb96/mysite/venv python-path=/home/benbb96/mysite/
        WSGIScriptAlias / /home/benbb96/mysite/config/wsgi.py
</VirtualHost>

我在使用wsgi以守护进程模式运行我的网站(具体可以参考文档),并且我想保护一些上传到protected/文件夹的媒体文件。所以我添加了一个<Directory>指令来阻止对这个文件夹的访问,然后在我的视图中使用XSendFile,它还会检查用户是否有权限访问这个文件,以便提供受保护的文件。

需要注意的是,我的静态文件和媒体文件是存放在一个网络挂载的文件夹中(/mnt/),但这并没有造成任何问题。

5

还要确保在你的Apache配置文件中设置XSendFilePath,像这样:

XSendFile on
XSendFilePath "//path/to/files/on/disk"
<Directory "//path/to/files/on/disk">
    Order Deny,Allow
    Allow from all
</Directory>

然后在返回响应的时候,把这个包含在你的视图中:

response['X-Sendfile'] = smart_str(file_path)

关于你的问题:

  • 在vhost标签中激活XSendFile
  • 我在上面已经写了在视图中还需要做什么
  • 我不确定你是否应该删除媒体别名,日志文件应该能告诉你是否有这个问题

撰写回答