Mam jednostronną aplikację internetową opartą na jquery. Komunikuje się z usługą internetową RESTful za pośrednictwem połączeń AJAX.
Próbuję wykonać następujące czynności:
- Prześlij POST zawierający dane JSON do adresu URL REST.
- Jeśli żądanie określa odpowiedź JSON, zwracana jest JSON.
- Jeśli żądanie określa odpowiedź w formacie PDF / XLS / etc, zwracany jest plik binarny do pobrania.
Mam teraz 1 i 2, a aplikacja kliencka jquery wyświetla zwrócone dane na stronie WWW, tworząc elementy DOM na podstawie danych JSON. Mam również # 3 działający z punktu widzenia usługi sieciowej, co oznacza, że utworzy i zwróci plik binarny, jeśli otrzyma prawidłowe parametry JSON. Ale nie jestem pewien, jak najlepiej poradzić sobie z numerem 3 w kodzie javascript klienta.
Czy można odzyskać plik do pobrania z takiego wywołania ajax? Jak mogę pobrać i zapisać plik w przeglądarce?
$.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;
}
});
Serwer odpowiada następującymi nagłówkami:
Content-Disposition:attachment; filename=export-1282022272283.pdf
Content-Length:5120
Content-Type:application/pdf
Server:Jetty(6.1.11)
Innym pomysłem jest wygenerowanie pliku PDF i zapisanie go na serwerze i zwrócenie JSON, który zawiera adres URL pliku. Następnie wywołaj kolejne wywołanie w module obsługi sukcesu ajax, aby zrobić coś takiego:
success: function(json,status) {
window.location.href = json.url;
}
Ale robienie tego oznacza, że musiałbym wykonać więcej niż jedno połączenie z serwerem, a mój serwer musiałby budować pliki do pobrania, przechowywać je gdzieś, a następnie okresowo czyścić ten obszar pamięci.
Musi istnieć prostszy sposób na osiągnięcie tego. Pomysły?
EDYCJA: Po przejrzeniu dokumentacji dla $ .ajax, widzę, że typ danych odpowiedzi może być tylko jeden xml, html, script, json, jsonp, text
, więc zgaduję, że nie ma sposobu na bezpośrednie pobranie pliku za pomocą żądania ajax, chyba że osadzę plik binarny przy użyciu Schemat URI danych, jak sugerowano w odpowiedzi @VinayC (nie jest to coś, co chcę zrobić).
Sądzę więc, że moje opcje to:
Nie używaj ajax, a zamiast tego prześlij formularz formularza i umieść moje dane JSON w wartościach formularza. Prawdopodobnie musiałby zadzierać z ukrytymi ramkami iframe i tak dalej.
Nie używaj ajax i zamiast tego przekonwertuj moje dane JSON na ciąg zapytania, aby zbudować standardowe żądanie GET i ustawić window.location.href na ten adres URL. Może być konieczne użycie event.preventDefault () w moim module obsługi kliknięć, aby przeglądarka nie zmieniła adresu URL aplikacji.
Użyj mojego innego pomysłu powyżej, ale wzbogaconego sugestiami z odpowiedzi @naikus. Prześlij żądanie AJAX z pewnym parametrem, który informuje serwis internetowy o wywołaniu za pośrednictwem wywołania ajax. Jeśli usługa internetowa jest wywoływana z wywołania ajax, po prostu zwróć JSON z adresem URL do wygenerowanego zasobu. Jeśli zasób jest wywoływany bezpośrednio, zwróć rzeczywisty plik binarny.
Im więcej o tym myślę, tym bardziej podoba mi się ostatnia opcja. W ten sposób mogę odzyskać informacje o żądaniu (czas wygenerowania, rozmiar pliku, komunikaty o błędach itp.) I mogę działać na podstawie tych informacji przed rozpoczęciem pobierania. Minusem jest dodatkowe zarządzanie plikami na serwerze.
Jakieś inne sposoby na osiągnięcie tego? Jakieś zalety / wady tych metod, o których powinienem wiedzieć?
url = 'http://localhost/file.php?file='+ $('input').val(); window.open(url);
Prosty sposób na uzyskanie tych samych rezultatów. Umieść nagłówek w pliku php. Nie trzeba wysyłać żadnych