使用Django和Nginx X-accel-redirect提供受保护的文件 [英] Serving protected files with Django and Nginx X-accel-redirect

查看:68
本文介绍了使用Django和Nginx X-accel-redirect提供受保护的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试让Nginx和Django一起播放以提供可下载的受保护文件.我就是无法正常工作.这是我的Nginx配置:

I'm trying to get Nginx and Django to play together to serve downloadable protected files. I just cannot get it to work. Here's my Nginx config:

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

用于查看文件的相关urls.py:

the relevant urls.py for viewing the file(s):

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个值:

I have 2 values in my settings file:

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

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

_convert_file_to_url() takes the full file path and, using the two settings values above, turns it into a url that (I thought) Nginx would allow:

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

因此,如果我尝试访问:

So, if I try to access:

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

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

In my browser window, it doesn't allow it (404). Good.

但是-如果我尝试从我希望允许的表单下载中访问该URL,则会在浏览器中重定向到:

BUT - if I try to access that url from a form download, which I want to allow, I get a redirect in the browser to:

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

它也是404.

我已经尝试了很多不同的配置,但现在我的大脑已经痛了.:-)

I've tried so many different configurations my brain now hurts. :-)

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

Should I not be reading the file with open(), and let Nginx serve it? If I remove that line, it returns a file with the dreaded zero bytes. Why do I still get a 404 on the redirected url??

推荐答案

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

Should I not be reading the file with open(),

是正确的.您的脚本不应该打开文件.您只需告诉Nginx文件在哪里,然后让它打开文件并提供服务即可.

That's correct. Your script shouldn't be opening the file. You just tell Nginx where the file exists and let it open the file and serve it.

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

I believe you want to just return an empty response after setting the appropriate headers

return HttpResponse('', mimetype=contenttype)

在PHP中,我通过以下操作设置了Nginx accel重定向:

In PHP I setup the Nginx accel redirect by doing:

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

即设置标题后立即退出.

i.e. exiting immediately after setting the header.

对于仍然存在的404问题,您可能在Nginx conf中有一个错误,但是您需要发布其余内容以确保.您的外部URL类似于:

For the continuing 404 problem, you've probably got an error in the Nginx conf, but you need to post the rest to be sure. Your external URL appears to be something like:

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

这将与以下项匹配:

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

提供404.

在外部URL和内部URL中都没有必要(并且非常令人困惑)使用相同的词 protected-test .我建议您不要这样做,即让外部网址像这样:

There is no need (and it's quite confusing) to have the same word protected-test in both the external URL and internal URL. I'd recommend not doing that i.e. have the external URL be like:

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

然后将内部位置块设置为:

Then have the internal location block be:

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

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

And then when you setup the x-accel-redirect header, swap between the two:

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 这个字.

Rather than having the word protected-test be on both sides of the request.

这篇关于使用Django和Nginx X-accel-redirect提供受保护的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆