我正在尝试让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?
答案 0 :(得分: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中出错,但您需要发布其余的以确定。您的外部网址似乎如下:
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
这个词。