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