personalizado cabeçalhos HTTP para arquivos estáticos com Django
Pergunta
Eu estou escrevendo um banco de imagens com Django, e eu quero adicionar um botão para obter uma versão hi-res de uma imagem (os de baixa resolução é mostrada na página de detalhes). Se eu colocar apenas uma ligação <a>
, o navegador abrirá a imagem em vez de baixá-lo. Adicionando um cabeçalho HTTP como:
Content-Disposition: attachment; filename="beach008.jpg"
obras, mas já que é um arquivo estático, eu não quero lidar com o pedido com Django. Atualmente, estou usando NGINX para servir arquivos estáticos, e páginas dinâmicas são redirecionadas via FastCGI para o processo de Django. Estou pensando em usar comando add-header
NGINX, mas pode definir a parte filename="xx"
?. Ou talvez haja alguma maneira de lidar com o pedido no Django, mas certifique NGINX servir o conteúdo?
Solução
Se seu aplicativo Django é aproximada pela nginx você pode usar x-Accell redirecionamento . Você precisa passar um cabeçalho especial em sua resposta, nginx vai intercepet isso e começar a servir o arquivo, você também pode passar Content-Disposition na mesma resposta para forçar um download.
Essa solução é boa se você quiser controlar quais usuários acesso destes arquivos.
Você também pode usar uma configuração como esta:
#files which need to be forced downloads
location /static/high_res/ {
root /project_root;
#don't ever send $request_filename in your response, it will expose your dir struct, use a quick regex hack to find just the filename
if ($request_filename ~* ^.*?/([^/]*?)$) {
set $filename $1;
}
#match images
if ($filename ~* ^.*?\.((jpg)|(png)|(gif))$) {
add_header Content-Disposition "attachment; filename=$filename";
}
}
location /static {
root /project_root;
}
Isto irá forçar download em todas as imagens em alguns high_res pasta (mediaroot / high_rest). E para os outros arquivos estáticos ele vai se comportar como normal. Por favor note que este é um corte rápido modificada que funciona para mim. Ele pode ter implicações de segurança, para usá-lo com precaução.
Outras dicas
Eu escrevi um decorador simples, de vista django.views.static.serve
O que funciona para mim perfeitamente.
def serve_download(view_func):
def _wrapped_view_func(request, *args, **kwargs):
response = view_func(request, *args, **kwargs)
response['Content-Type'] = 'application/octet-stream';
import os.path
response['Content-Disposition'] = 'attachment; filename="%s"' % os.path.basename(kwargs['path'])
return response
return _wrapped_view_func
Além disso, você pode jogar com mime-types nginx
http://wiki.codemongers.com/NginxHttpCoreModule#types
Esta solução não funcionou para mim, porque eu queria ter tanto link direto para o arquivo (assim que o usuário pode visualizar imagens, por exemplo), e link para download.
O que eu estou fazendo agora é usar um URL diferente para download do que para 'vistas', e adicionar o nome do arquivo como um arg URL:
meios habituais link: http://xx.com/media/images/lores/f_123123.jpg
Download link: http://xx.com/downs/hires/f_12323?beach008.jpg
e nginx tem uma configuração como esta:
location /downs/ {
root /var/www/nginx-attachment;
add_header Content-Disposition 'attachment; filename="$args"';
}
mas eu realmente não gosto do cheiro.