Eu tenho um webapp de página única baseado em jquery. Ele se comunica com um serviço da web RESTful por meio de chamadas AJAX.
Estou tentando fazer o seguinte:
- Envie um POST que contenha dados JSON para um URL REST.
- Se a solicitação especificar uma resposta JSON, JSON será retornado.
- Se a solicitação especificar uma resposta PDF / XLS / etc, um binário para download será retornado.
Eu tenho 1 e 2 trabalhando agora, e o aplicativo jquery do cliente exibe os dados retornados na página da web, criando elementos DOM com base nos dados JSON. Eu também tenho o # 3 trabalhando do ponto de vista do serviço da web, o que significa que ele criará e retornará um arquivo binário se tiver os parâmetros JSON corretos. Mas não tenho certeza da melhor maneira de lidar com o número 3 no código javascript do cliente.
É possível recuperar um arquivo para download a partir de uma chamada ajax como esta? Como obtenho o navegador para baixar e salvar o arquivo?
$.ajax({
type: "POST",
url: "/services/test",
contentType: "application/json",
data: JSON.stringify({category: 42, sort: 3, type: "pdf"}),
dataType: "json",
success: function(json, status){
if (status != "success") {
log("Error loading data");
return;
}
log("Data loaded!");
},
error: function(result, status, err) {
log("Error loading data");
return;
}
});
O servidor responde com os seguintes cabeçalhos:
Content-Disposition:attachment; filename=export-1282022272283.pdf
Content-Length:5120
Content-Type:application/pdf
Server:Jetty(6.1.11)
Outra idéia é gerar o PDF e armazená-lo no servidor e retornar JSON que inclui uma URL para o arquivo. Em seguida, emita outra chamada no manipulador de sucesso do ajax para fazer algo como o seguinte:
success: function(json,status) {
window.location.href = json.url;
}
Mas fazer isso significa que eu precisaria fazer mais de uma chamada para o servidor, e meu servidor precisaria criar arquivos para download, armazená-los em algum lugar e, em seguida, limpar periodicamente a área de armazenamento.
Deve haver uma maneira mais simples de conseguir isso. Ideias?
EDIT: Depois de revisar os documentos para $ .ajax, vejo que o dataType de resposta pode ser apenas um deles xml, html, script, json, jsonp, text
, então acho que não há como baixar diretamente um arquivo usando uma solicitação ajax, a menos que eu incorpore o arquivo binário usando Esquema de URI de dados, conforme sugerido na resposta @VinayC (que não é algo que eu quero fazer).
Então, acho que minhas opções são:
Não use ajax e, em vez disso, envie uma postagem de formulário e incorpore meus dados JSON aos valores do formulário. Provavelmente precisaria mexer com iframes ocultos e tal.
Não use ajax e, em vez disso, converta meus dados JSON em uma sequência de consultas para criar uma solicitação GET padrão e defina window.location.href para este URL. Pode ser necessário usar event.preventDefault () no meu manipulador de cliques para impedir que o navegador seja alterado a partir do URL do aplicativo.
Use minha outra idéia acima, mas aprimorada com sugestões da resposta @naikus. Envie a solicitação AJAX com algum parâmetro que permita ao serviço da web saber que isso está sendo chamado por meio de uma chamada ajax. Se o serviço da web for chamado a partir de uma chamada ajax, basta retornar JSON com uma URL para o recurso gerado. Se o recurso for chamado diretamente, retorne o arquivo binário real.
Quanto mais eu penso sobre isso, mais eu gosto da última opção. Dessa forma, posso recuperar informações sobre a solicitação (tempo para gerar, tamanho do arquivo, mensagens de erro etc.) e posso agir com base nessas informações antes de iniciar o download. A desvantagem é o gerenciamento extra de arquivos no servidor.
Existem outras maneiras de conseguir isso? Quaisquer prós / contras para esses métodos dos quais devo estar ciente?
url = 'http://localhost/file.php?file='+ $('input').val(); window.open(url);
A maneira mais fácil de obter os mesmos resultados. Coloque o cabeçalho no arquivo php. Não há necessidade de enviar qualquer ajax ou obter pedidos