Partindo de Curitiba as 17h com destino a Porto Alegre.
Para os que vão, nos vemos lá! :)
Primeiro post pelo Planeta GNU/Linux Brasil. :)
Essa semana precisei criar uma aplicação web que disponibilizasse alguns arquivos para download e então decidi fazer isso utilizando Python e Django.
Uma parte da minha aplicação consistia em forçar o browser a abrir uma janela de download ao invés de exibir o arquivo (como acontece no caso de imagens ou arquivos texto). Eu já havia feito isso algumas vezes em PHP, mas fui pesquisar para ver se o Django não possuia alguma função pronta que me facilitasse essa tarefa, algo como:
return HttpResponseFile(file)
Passei algum tempo procurando por alguma solução mais inteligente do que alterar o header na mão, mas não consegui encontrar nada. Fui então atrás da documentação oficial, para descobrir como eu podia aplicar a solução que eu já utilizava em PHP para a realidade do Django. Encontrei aqui a “receita de bolo” de como alterar o header da requisição e fazer com que o browser agisse da forma como eu queria.
Portanto segue abaixo, a parte principal da minha implementação:
urls.py
Esse arquivo tem uma única função: extrair da url o nome do arquivo a ser baixado e passa-lo como parametro para a view.
urlpatterns = patterns('',
(r'(?P<file>(^.*$)', 'myproject.apps.download.views.index'),
)
views.py
Aqui é onde a mágica ocorre… na verdade não é nada muito mágico, mas enfim. :)
Essa view apenas verifica se o arquivo existe e o envia para download, caso o arquivo não exista, retorna a página 404. Nessa função você pode aplicar várias outras validações, como verificar se o usuário está logado ou se ele relamente tem acesso a esse arquivo, etc. porém nada disso era necessário no meu caso.
from django.http import HttpResponse, Http404
from django.conf import settings
from os import path
import mimetypes
def index(request, file=''):
abspath = path.join(settings.BASEPATH, 'your/path', file)
if not (file and path.exists(abspath)):
raise Http404()
mimetype, encoding = mimetypes.guess_type(abspath)
if mimetype is None:
mimetype = 'application/force-download'
response = HttpResponse(open(abspath, 'r').read())
response['Content-Type'] = mimetype
response['Pragma'] = 'public'
response['Expires'] = '0'
response['Cache-Control'] = 'must-revalidate, post-check=0, pre-check=0'
response['Content-Disposition'] = 'attachment; filename=%s' % file
response['Content-Transfer-Encoding'] = 'binary'
response['Content-Length'] = str(path.getsize(abspath))
return response
Espero que seja de alguma utilidade… e se alguém tiver uma solução melhor! Por favor, poste nos comentários.
Não faz muito tempo que eu mexo com Django, mas estou gostando da brincadeira!
Acredito que o número de posts sobre Python desse blog tende a crescer consideravelmente… e isso é bom!
UPDATE1: Depois de algum tempo com o sistema em produção, foi constatado que a solução acima não funciona em algumas versão do Internet Explorer 7. A solução do problema também foi documentada e está disponível aqui.
UPDATE2: Adicionada a sugestão de Alexander Benatti com relação a criação da variável abspath.