Eu tenho uma ação do Struts2 no lado do servidor para baixar arquivos.
<action name="download" class="com.xxx.DownAction">
<result name="success" type="stream">
<param name="contentType">text/plain</param>
<param name="inputName">imageStream</param>
<param name="contentDisposition">attachment;filename={fileName}</param>
<param name="bufferSize">1024</param>
</result>
</action>
No entanto, quando eu chamo a ação usando o jQuery:
$.post(
"/download.action",{
para1:value1,
para2:value2
....
},function(data){
console.info(data);
}
);
no Firebug, vejo que os dados são recuperados com o fluxo binário . Gostaria de saber como abrir a janela de download de arquivos com a qual o usuário pode salvar o arquivo localmente?
Respostas:
Atualização dos navegadores modernos de 2019
Esta é a abordagem que eu recomendaria agora com algumas ressalvas:
2012 Abordagem baseada em jQuery / iframe / cookie original em 2012
Bluish está completamente certo sobre isso, você não pode fazer isso através do Ajax porque o JavaScript não pode salvar arquivos diretamente no computador do usuário (por questões de segurança). Infelizmente, apontar o URL da janela principal para o download do arquivo significa que você tem pouco controle sobre a experiência do usuário quando ocorre o download do arquivo.
Criei o jQuery File Download, que permite uma experiência "semelhante ao Ajax" com downloads de arquivos completos com retornos de chamada OnSuccess e OnFailure para proporcionar uma melhor experiência ao usuário. Dê uma olhada no meu post no blog sobre o problema comum que o plug-in resolve e algumas maneiras de usá-lo e também uma demonstração do jQuery File Download em ação . Aqui está a fonte
Aqui está uma demonstração simples de caso de uso usando a fonte do plugin com promessas. A página de demonstração inclui muitos outros exemplos de 'melhor UX'.
Dependendo de quais navegadores você precisa oferecer suporte, você poderá usar https://github.com/eligrey/FileSaver.js/, que permite um controle mais explícito do que o método IFRAME que o jQuery File Download usa.
fonte
Ninguém postou esta solução da @ Pekka ... então eu a postarei. Pode ajudar alguém.
Você não precisa fazer isso através do Ajax. Apenas use
fonte
window.open(<url>, '_blank');
para garantir que o download não substitua o conteúdo atual do navegador (independentemente do cabeçalho Disposição de conteúdo).POST
solicitação.Você pode com HTML5
NB: Os dados do arquivo retornados DEVEM ser codificados em base64 porque você não pode codificar JSON dados binários
Na minha
AJAX
resposta, tenho uma estrutura de dados que se parece com isso:Isso significa que eu posso fazer o seguinte para salvar um arquivo via AJAX
A função base64ToBlob foi retirada daqui e deve ser usada em conformidade com esta função
Isso é bom se o servidor estiver despejando dados arquivados para serem salvos. No entanto, eu ainda não descobri como implementar um fallback HTML4
fonte
a.click()
parece não funcionar no firefox ... Alguma idéia?a
ao dom para que este código funcione e / ou remova arevokeObjectURL
parte:document.body.appendChild(a)
var bytechars = atob(base64)
emite um erroJavaScript runtime error: InvalidCharacterError
. Estou usando a versão 75.0.3770.142 do Chrome, mas não sei o que há de errado aqui.1. Independente da estrutura: Servlet baixando arquivo como anexo
2. Struts2 Framework: Ação baixando arquivo como anexo
Seria melhor usar a
<s:a>
tag apontando com OGNL para um URL criado com a<s:url>
tag:Nos casos acima, você precisa gravar o cabeçalho Disposição de Conteúdo na resposta , especificando que o arquivo precisa ser baixado (
attachment
) e não aberto pelo navegador (inline
). Você também precisa especificar o Tipo de conteúdo e adicionar o nome e o comprimento do arquivo (para ajudar o navegador a desenhar uma barra de progresso realista).Por exemplo, ao baixar um ZIP:
Com o Struts2 (a menos que você esteja usando a Ação como um Servlet, um hack para transmissão direta , por exemplo), você não precisa escrever nada diretamente na resposta; simplesmente usar o tipo de resultado Stream e configurá-lo em struts.xml funcionará: EXEMPLO
3. Agnóstico da estrutura (estrutura / Struts2): arquivo de abertura do servlet (/ Ação) dentro do navegador
Se você deseja abrir o arquivo dentro do navegador, em vez de baixá-lo, a disposição do Conteúdo deve ser configurada para embutida , mas o destino não pode ser o local atual da janela; você deve direcionar uma nova janela criada por javascript, uma
<iframe>
na página ou uma nova janela criada on-the-fly com o "discutido" target = "_ blank":fonte
too long url
erro.A maneira simples de fazer o navegador baixar um arquivo é fazer a solicitação assim:
Isso abre o pop-up de download do navegador.
fonte
Criei pouca função como solução alternativa (inspirada no plugin @JohnCulviner):
Demonstração com evento de clique:
fonte
Eu enfrentei o mesmo problema e resolvi-o com sucesso. Meu caso de uso é esse.
" Publique dados JSON no servidor e receba um arquivo do Excel. Esse arquivo do Excel é criado pelo servidor e retornado como resposta ao cliente. Faça o download dessa resposta como um arquivo com nome personalizado no navegador "
O snippet acima está apenas seguindo
Aqui, precisamos definir cuidadosamente algumas coisas no lado do servidor. Eu defini alguns cabeçalhos no Python Django HttpResponse. Você precisa configurá-los de acordo se usar outras linguagens de programação.
Desde que eu baixei xls (excel) aqui, ajustei contentType para acima de um. Você precisa configurá-lo de acordo com o seu tipo de arquivo. Você pode usar esta técnica para baixar qualquer tipo de arquivo.
fonte
HTMLAnchorElement.download
, estou pensando em combiná-lo com o método proprietário msSaveOrOpenBlob .Ok, com base no código do ndpu, aqui está uma versão melhorada (eu acho) do ajax_download; -
Use isso assim; -
Os parâmetros são enviados como pós-parâmetros adequados, como se viessem de uma entrada, e não como uma string codificada por json, como no exemplo anterior.
CAVEAT: Tenha cuidado com o potencial de injeção variável nesses formulários. Pode haver uma maneira mais segura de codificar essas variáveis. Como alternativa, considere escapar deles.
fonte
Uncaught SecurityError: Blocked a frame with origin "http://foo.bar.com" from accessing a frame with origin "null". The frame requesting access has a protocol of "http", the frame being accessed has a protocol of "data". Protocols must match.
@ResourceMapping() public void downloadFile(final ResourceRequest request, final ResourceResponse response, @ModelAttribute("downForm") FormModel model)
mas não está funcionando ..Aqui está o que eu fiz, javascript puro e html. Não o testou, mas isso deve funcionar em todos os navegadores.
fonte
fonte
download
atributo, para que o seu ficheiro vai acabar por ter o nome de "Desconhecido"No Rails, faço da seguinte maneira:
O truque é a parte window.location . O método do controlador é semelhante a:
fonte
Use
window.open
https://developer.mozilla.org/en-US/docs/Web/API/Window/openPor exemplo, você pode colocar esta linha de código em um manipulador de cliques:
Ele abrirá uma nova guia (por causa do nome da janela '_blank') e essa guia abrirá o URL.
Seu código do servidor também deve ter algo como isto:
Dessa forma, o navegador deve solicitar ao usuário que salve o arquivo no disco, em vez de apenas mostrar o arquivo. Também fechará automaticamente a guia que acabou de abrir.
fonte
Tento baixar um arquivo CSV e, em seguida, faço algo após a conclusão do download. Então, eu preciso implementar uma adequada
callback
função .Usando
window.location="..."
não é uma boa ideia, porque não consigo operar o programa após concluir o download. Algo assim, mude o cabeçalho para que não seja uma boa ideia.fetch
é uma boa alternativa, no entanto , não suporta o IE 11 . Ewindow.URL.createObjectURL
não suporta o IE 11. Você pode consultar isso .Este é o meu código, é semelhante ao código de Shahrukh Alam. Mas você deve tomar cuidado para
window.URL.createObjectURL
talvez criar vazamentos de memória. Você pode consultar isso . Quando a resposta chegar, os dados serão armazenados na memória do navegador. Portanto, antes de clicar noa
link, o arquivo foi baixado. Isso significa que você pode fazer qualquer coisa após o download.fonte
Como baixar um arquivo após recebê-lo pelo AJAX
É conveniente quando o arquivo é criado por um longo tempo e você precisa mostrar PRELOADER
Exemplo ao enviar um formulário da web:
O funcional opcional é comentado para simplificar o exemplo.
Não há necessidade de criar arquivos temporários no servidor.
No jQuery v2.2.4, clique em OK. Haverá um erro na versão antiga:
fonte
filename.match(/filename=(.*)/)[1]
(sem as aspas duplas ou o ponto de interrogação) - regex101.com/r/2AsD4y/2 . No entanto, sua solução foi a única solução que funcionou após muita pesquisa.Adicionando mais algumas coisas à resposta acima para baixar um arquivo
Abaixo está um código java spring que gera uma matriz de bytes
Agora no código javascript usando o FileSaver.js, é possível baixar um arquivo com o código abaixo
O arquivo acima fará o download do arquivo
fonte
Ok, então aqui está o código de funcionamento ao usar o MVC e você está obtendo seu arquivo de um controlador
digamos que você tenha sua matriz de bytes declarada e preenchida, a única coisa que você precisa fazer é usar a função Arquivo (usando System.Web.Mvc)
e depois, no mesmo controlador, adicione estas 2 funções
e você poderá ligar para o seu controlador para fazer o download e obter o retorno de chamada "sucesso" ou "falha"
fonte
Eu encontrei uma correção que, embora não esteja usando o ajax, permite que você use uma chamada javascript para solicitar o download e obtenha um retorno de chamada quando o download realmente começar. Achei isso útil se o link executar um script do lado do servidor que demore um pouco para compor o arquivo antes de enviá-lo. para que você possa alertá-los de que está processando e, quando finalmente enviar o arquivo, remova a notificação de processamento. é por isso que eu queria tentar carregar o arquivo via ajax para começar, para que um evento acontecesse quando o arquivo fosse solicitado e outro quando ele realmente iniciar o download.
os js na primeira página
o iframe
então o outro arquivo:
Eu acho que há uma maneira de ler obter dados usando js, então nenhum php seria necessário. mas eu não sei de antemão e o servidor que estou usando suporta php, então isso funciona para mim. pensei em compartilhá-lo no caso de ajudar alguém.
fonte
Se você deseja usar o Download de arquivo jQuery, observe isso no IE. Você precisa redefinir a resposta ou ela não será baixada
Sua ação pode ser implementada
ServletResponseAware
para acessargetServletResponse()
fonte
É certo que você não pode fazê-lo através da chamada Ajax.
No entanto, há uma solução alternativa.
Passos :
Se você estiver usando o form.submit () para baixar o arquivo, o que você pode fazer é:
Isso é útil no caso de você decidir se o arquivo precisa ou não ser baixado após fazer o formulário.submit (), por exemplo: pode haver um caso em que no formulário.submit () ocorre uma exceção no servidor e, em vez disso, do travamento, pode ser necessário mostrar uma mensagem personalizada no lado do cliente; nesse caso, essa implementação pode ajudar.
fonte
existe outra solução para baixar uma página da web no ajax. Mas estou me referindo a uma página que deve primeiro ser processada e depois baixada.
Primeiro, você precisa separar o processamento da página do download dos resultados.
1) Apenas os cálculos da página são feitos na chamada ajax.
Espero que esta solução possa ser útil para muitos, como foi para mim.
fonte
fonte
É isso que funciona tão bem em qualquer navegador (estou usando o núcleo do asp.net)
fonte
Eu lutei com esse problema por um longo tempo. Finalmente, uma elegante biblioteca externa sugerida aqui me ajudou.
fonte