【问题标题】:Serving protected files with Django and Nginx X-accel-redirect使用 Django 和 Nginx X-accel-redirect 提供受保护的文件
【发布时间】:2013-04-19 21:14:48
【问题描述】:

我正在尝试让 Nginx 和 Django 一起玩以提供可下载的受保护文件。我只是无法让它工作。这是我的 Nginx 配置:

location ~ ^.*/protected-test/ {
alias /<path-to-my-protected-files-on-server>/;
internal;
}

查看文件的相关 urls.py:

url(r'^static_files/downloads/protected-test/(?P<filename>.+)$', 'download_or_view',
{'download_dir': '%s%s' % (settings.MEDIA_ROOT, 'downloads/protected-test/'),
'content_disposition_type': 'inline',
'protected': 'True'},
name='protected_files')

我的看法:

def download_or_view(request, content_disposition_type, download_dir, filename=None, protected=False):

'''Allow a file to be downloaded or viewed,based on the request type and
     content disposition value.'''

if request.method == 'POST':
    full_path = '%s%s' % (download_dir, request.POST['filename'])
    short_filename = str(request.POST['filename'])
else:
    full_path = '%s%s' % (download_dir, filename)
    short_filename = str(filename)

serverfile = open(full_path, 'rb')
contenttype, encoding = mimetypes.guess_type(short_filename)
response = HttpResponse(serverfile, mimetype=contenttype)

if protected:
    url = _convert_file_to_url(full_path)
    response['X-Accel-Redirect'] = url.encode('utf-8')

response['Content-Disposition'] = '%s; filename="%s"' % (content_disposition_type, smart_str(short_filename))
response['Content-Length'] = os.stat(full_path).st_size

return response

我的设置文件中有 2 个值:

NGINX_ROOT = (os.path.join(MEDIA_ROOT, 'downloads/protected-test'))
NGINX_URL = '/protected-test'

_convert_file_to_url() 采用完整的文件路径,并使用上面的两个设置值,将其转换为(我认为)Nginx 允许的 url:

<domain-name>/protected-test/<filename>

所以,如果我尝试访问:

<domain-name>/static_files/downloads/protected-test/<filename>

在我的浏览器窗口中,它不允许 (404)。很好。

但是 - 如果我尝试从我想要允许的表单下载访问该 url,我会在浏览器中获得重定向到:

<domain-name>/protected-test/<filename>

它也是一个 404。

我尝试了很多不同的配置,现在我的大脑很疼。 :-)

我不应该用 open() 读取文件,让 Nginx 服务它吗?如果我删除该行,它会返回一个包含可怕的零字节的文件。为什么我仍然在重定向的 url 上得到 404??

【问题讨论】:

    标签: django nginx x-accel-redirect


    【解决方案1】:

    我不应该用 open() 读取文件吗,

    没错。您的脚本不应该打开文件。你只需告诉 Nginx 文件存在的位置,让它打开文件并提供它。

    我相信您只想在设置适当的标头后返回一个空响应

    return HttpResponse('', mimetype=contenttype)
    

    在 PHP 中,我通过以下方式设置 Nginx 加速重定向:

    //Set content type and caching headers
    //...
    header("X-Accel-Redirect: ".$filenameToProxy);
    exit(0);
    

    即设置标题后立即退出。

    对于持续的 404 问题,您可能在 Nginx conf 中遇到了错误,但您需要发布其余部分以确定。您的外部 URL 类似于:

    static_files/downloads/protected-test/(?P<filename>.+)$
    

    这将匹配:

    location ~ ^.*/protected-test/ {
        alias /<path-to-my-protected-files-on-server>/;
        internal;
    }
    

    给出 404。

    没有必要(这很令人困惑)在外部 URL 和内部 URL 中使用相同的词 protected-test。我建议不要这样做,即外部 URL 类似于:

    /static_files/downloads/(?P<filename>.+)$
    

    然后将内部位置块设为:

    location ~ ^/protected-test {
        alias /<path-to-my-protected-files-on-server>;
        internal;
    }
    

    然后当您设置 x-accel-redirect 标头时,在两者之间交换:

    external_path = "/static_files/downloads";
    nginx_path = "/protected-test";
    filenameToProxy = str_replace(external_path, nginx_path, full_path);
    header("X-Accel-Redirect: ".$filenameToProxy);
    

    而不是让protected-test 出现在请求的两侧。

    【讨论】:

    • K,谢谢,这是固定的一件事 - 但在更改后提供文件仍然没有运气。
    • 你能把剩下的 nginx conf 贴出来吗?
    • 第三方为我配置了nginx conf,我会尽快贴上来。他们说这是皇帝模式下的默认配置,加上上面的内部声明。
    • 最好不要同时命名/protected-test,我会试试的。我还注意到您的内部配置为“~/protected-test”,没有结尾斜杠。这会和我的 conf 有什么不同吗?
    • 它不应该——只要你能确定结局是否存在。 Nginx 将位置块的匹配文本之后的任何内容附加到别名。所以 /protected-test/anything 将被映射到 //anything 。我认为唯一的问题可能是您在位置块中有斜杠但将其保留在别名路径之外 - 这不会解析为真实文件。
    猜你喜欢
    • 2015-04-29
    • 2013-04-17
    • 2018-02-02
    • 2019-03-26
    • 1970-01-01
    • 2012-09-01
    • 2021-12-24
    • 1970-01-01
    相关资源
    最近更新 更多