Mam stronę, która pozwala użytkownikowi pobrać plik generowany dynamicznie. Generowanie zajmuje dużo czasu, więc chciałbym pokazać wskaźnik „czekania”. Problem polega na tym, że nie mogę ustalić, jak wykryć, kiedy przeglądarka otrzyma plik, więc mogę ukryć wskaźnik.
Zgłaszam żądanie w ukrytej formie, które POST wysyła do serwera i kieruje wyniki do ukrytej ramki iframe. Dzieje się tak, dlatego nie zastępuję całego okna przeglądarki wynikiem. Słucham zdarzenia „load” w ramce iframe, w nadziei, że zadziała po zakończeniu pobierania.
Z plikiem zwracam nagłówek „Content-Disposition: załącznik”, co powoduje, że przeglądarka wyświetla okno dialogowe „Zapisz”. Ale przeglądarka nie uruchamia zdarzenia „load” w ramce iframe.
Jednym ze sposobów, które wypróbowałem, jest użycie odpowiedzi wieloczęściowej. Wyśle więc pusty plik HTML, a także załączony plik do pobrania. Na przykład:
Content-type: multipart/x-mixed-replace;boundary="abcde"
--abcde
Content-type: text/html
--abcde
Content-type: application/vnd.fdf
Content-Disposition: attachment; filename=foo.fdf
file-content
--abcde
Działa to w przeglądarce Firefox; otrzymuje pusty plik HTML, uruchamia zdarzenie „ładuj”, a następnie wyświetla okno dialogowe „Zapisz” dla pliku do pobrania. Ale zawodzi w IE i Safari; IE uruchamia zdarzenie „ładuj”, ale nie pobiera pliku, a Safari pobiera plik (z niewłaściwą nazwą i typem zawartości) i nie uruchamia zdarzenia „ładuj”.
Innym podejściem może być wywołanie w celu rozpoczęcia tworzenia pliku, następnie odpytanie serwera, aż będzie on gotowy, a następnie pobranie już utworzonego pliku. Ale wolałbym unikać tworzenia plików tymczasowych na serwerze.
Czy ktoś ma lepszy pomysł?
źródło
Odpowiedzi:
Jedno możliwe rozwiązanie wykorzystuje JavaScript na kliencie.
Algorytm klienta:
Algorytm serwera:
Kod źródłowy klienta (JavaScript):
Przykładowy kod serwera (PHP):
Gdzie:
źródło
Bardzo prostym (i kiepskim) rozwiązaniem jednoliniowym jest użycie
window.onblur()
zdarzenia do zamknięcia okna ładowania. Oczywiście, jeśli potrwa to zbyt długo, a użytkownik zdecyduje się zrobić coś innego (np. Czytanie wiadomości e-mail), okno ładowania zostanie zamknięte.źródło
onbeforeunload
Dziękujemy.stary wątek, wiem ...
ale te, które są tu prowadzone przez Google, mogą być zainteresowane moim rozwiązaniem. jest bardzo prosty, ale niezawodny. i umożliwia wyświetlanie rzeczywistych komunikatów o postępach (i można je łatwo podłączyć do istniejących procesów):
skrypt, który przetwarza (moim problemem było: pobieranie plików przez http i dostarczanie ich jako zip) zapisuje status do sesji.
status jest odpytywany i wyświetlany co sekundę. to wszystko (ok, to nie. musisz zadbać o wiele szczegółów [np. jednoczesne pobieranie], ale jest to dobre miejsce, aby zacząć ;-)).
strona pobierania:
getstatus.php
download.php
źródło
.each()
do rejestracji zdarzeń. po prostu powiedz$('a.download').click()
setTimeout('getstatus()', 1000);
. Użyj fn bezpośrednio:setTimeout(getstatus, 1000);
Korzystam z poniższych, aby pobrać obiekty BLOB i odwołać adres URL obiektu po pobraniu. działa w Chrome i Firefox!
po zamknięciu okna pobierania pliku okno odzyskuje fokus, co powoduje wyzwolenie zdarzenia fokusa.
źródło
Na podstawie przykładu Elmera przygotowałem własne rozwiązanie. Po kliknięciu elementów ze zdefiniowaną klasą pobierania pozwala wyświetlić niestandardowy komunikat na ekranie. Użyłem skupienia wyzwalacza aby ukryć wiadomość.
JavaScript
HTML
Teraz powinieneś zaimplementować dowolny element do pobrania:
lub
Po każdym kliknięciu pobierania zobaczysz komunikat, który tworzy raport, proszę czekać ...
źródło
Napisałem prostą klasę JavaScript, która implementuje technikę podobną do tej opisanej w żartobliwej odpowiedzi . Mam nadzieję, że może się tu przydać. Projekt GitHub nazywa się response-monitor.js
Domyślnie używa spin.js jako wskaźnika oczekiwania, ale zapewnia również zestaw zwrotnych implementacji niestandardowego wskaźnika.
JQuery jest obsługiwany, ale nie wymagany.
Ważne funkcje
Przykładowe użycie
HTML
Klient (zwykły JavaScript)
Klient (JQuery)
Klient z wywołaniami zwrotnymi (JQuery)
Serwer (PHP)
Aby uzyskać więcej przykładów, sprawdź folder przykładów w repozytorium.
źródło
Jestem spóźniony na przyjęcie, ale umieszczę to tutaj, jeśli ktoś inny chciałby poznać moje rozwiązanie:
Naprawdę zmagałem się z tym dokładnie problemem, ale znalazłem realne rozwiązanie przy użyciu ramek iframe (wiem, wiem. To okropne, ale działa na prosty problem, który miałem)
Miałem stronę HTML, która uruchomiła osobny skrypt php, który wygenerował plik, a następnie go pobrał. Na stronie html użyłem następującej jquery w nagłówku html (musisz również dołączyć bibliotekę jquery):
Na your_download_script.php:
Aby rozwiązać ten problem, jquery najpierw uruchamia skrypt php w ramce iframe. Ramka iframe jest ładowana po wygenerowaniu pliku. Następnie jquery ponownie uruchamia skrypt ze zmienną żądania, która nakazuje skryptowi pobranie pliku.
Przyczyną niemożności pobrania i wygenerowania pliku za jednym razem jest funkcja php header (). Jeśli używasz header (), zmieniasz skrypt na coś innego niż strona internetowa i jquery nigdy nie rozpoznaje skryptu pobierania jako „załadowanego”. Wiem, że niekoniecznie wykrywa to, kiedy przeglądarka odbiera plik, ale twój problem brzmiał podobnie do mojego.
źródło
Jeśli przesyłasz strumieniowo plik, który generujesz dynamicznie, a także masz zaimplementowaną bibliotekę wiadomości między serwerami w czasie rzeczywistym, możesz dość łatwo ostrzec swojego klienta.
Biblioteczną komunikację między serwerami a klientami, którą lubię i polecam, to Socket.io (via Node.js). Po zakończeniu skryptu serwera generowanie pliku przesyłanego strumieniowo w celu pobrania ostatniej linii w tym skrypcie może wysłać komunikat do Socket.io, który wysyła powiadomienie do klienta. Na kliencie Socket.io nasłuchuje przychodzących wiadomości emitowanych z serwera i umożliwia działanie na nich. Zaletą korzystania z tej metody w porównaniu z innymi jest to, że po zakończeniu przesyłania strumieniowego można wykryć „prawdziwe” zdarzenie zakończenia.
Na przykład możesz pokazać wskaźnik zajętości po kliknięciu łącza pobierania, przesłać strumieniowo plik, wysłać wiadomość do Socket.io z serwera w ostatnim wierszu skryptu przesyłania strumieniowego, nasłuchiwać na kliencie powiadomienia, odbierać powiadomienia i zaktualizuj interfejs użytkownika, ukrywając wskaźnik zajętości.
Zdaję sobie sprawę, że większość osób czytających odpowiedzi na to pytanie może nie mieć tego typu konfiguracji, ale użyłem tego dokładnego rozwiązania z wielkim efektem w moich własnych projektach i działa on cudownie.
Socket.io jest niezwykle łatwy w instalacji i obsłudze. Zobacz więcej: http://socket.io/
źródło
„Jak wykryć, kiedy przeglądarka otrzymuje pobieranie pliku?”
Z tą konfiguracją napotkałem ten sam problem:
struts 1.2.9
jquery-1.3.2.
jquery-ui-1.7.1.custom
IE 11
java 5
Moje rozwiązanie z plikiem cookie:
- po stronie klienta: przy
przesyłaniu formularza wywołaj funkcję javascript, aby ukryć stronę i załadować oczekujący spinner
Następnie wywołaj funkcję, która będzie sprawdzać co 500 ms, czy plik cookie pochodzi z serwera.
Jeśli plik cookie zostanie znaleziony, przestań sprawdzać co 500 ms , wygaś plik cookie i wywołaj swoją funkcję, aby wrócić do strony i usunąć oczekujące pokrętło (removeWaitingSpinner () ). Ważne jest, aby wygasnąć plik cookie, jeśli chcesz ponownie pobrać kolejny plik!
- Strona serwera:
pod koniec procesu serwera dodaj plik cookie do odpowiedzi. Ten plik cookie zostanie wysłany do klienta, gdy plik będzie gotowy do pobrania.
Mam nadzieję, że komuś pomogę!
źródło
Gdy użytkownik uruchomi generowanie pliku, możesz po prostu przypisać unikalny identyfikator do tego „pobierania” i wysłać użytkownika na stronę, która odświeża (lub sprawdza za pomocą AJAX) co kilka sekund. Po zakończeniu pliku zapisz go pod tym samym unikalnym identyfikatorem i ...
Następnie możesz pominąć cały bałagan iframe / waiting / browserwindow, ale mieć naprawdę eleganckie rozwiązanie.
źródło
Jeśli nie chcesz generować i przechowywać pliku na serwerze, czy chcesz zapisać status, np. Plik w toku, plik kompletny? Twoja strona „oczekiwania” może sondować serwer, aby dowiedzieć się, kiedy generowanie pliku zostało zakończone. Nie wiedziałbyś na pewno, że przeglądarka rozpoczęła pobieranie, ale byłbyś pewien.
źródło
Właśnie miałem ten sam problem. Moim rozwiązaniem było użycie plików tymczasowych, ponieważ generowałem już kilka plików tymczasowych. Formularz jest przesyłany z:
Na końcu skryptu generującego plik mam:
Spowoduje to uruchomienie zdarzenia ładowania w ramce iframe. Następnie komunikat oczekiwania zostanie zamknięty, a następnie rozpocznie się pobieranie pliku. Testowane na IE7 i Firefox.
źródło
Z mojego doświadczenia wynikają dwa sposoby:
źródło
Pozdrowienia, wiem, że temat jest stary, ale zostawiam rozwiązanie, które widziałem gdzie indziej i zadziałało:
Możesz tego użyć:
źródło
Jeśli masz pobrany plik, który jest zapisywany, a nie jest w dokumencie, nie ma sposobu, aby określić, kiedy pobieranie jest ukończone, ponieważ nie jest to zakres bieżącego dokumentu, ale osobny proces w przeglądarce.
źródło
Pytanie polega na tym, aby wskaźnik „oczekiwania” pojawiał się podczas generowania pliku, a następnie powracał do normalnego stanu po pobraniu pliku. Lubię to robić za pomocą ukrytej ramki iFrame i zaczepić zdarzenie onload ramki, aby moja strona wiedziała, kiedy pobieranie się rozpocznie. ALE onload nie uruchamia się w IE dla pobierania plików (jak w przypadku tokena nagłówka załącznika). Sondowanie serwera działa, ale nie lubię dodatkowej złożoności. Oto co robię:
Oświadczenie, nie rób tego na ruchliwej stronie, ponieważ buforowanie może się sumować. Ale tak naprawdę, jeśli twoje witryny, które są zajęte długim procesem, i tak pozbawią Cię wątków.
Oto, jak wygląda ludzkość, i to wszystko, czego naprawdę potrzebujesz.
źródło
Szybkim rozwiązaniem, jeśli chcesz wyświetlić wiadomość lub program ładujący do momentu wyświetlenia okna pobierania, jest umieszczenie wiadomości w ukrytym kontenerze, a po kliknięciu przycisku generującego plik do pobrania, kontener staje się widoczny. Następnie użyj jquery lub javascript, aby złapać zdarzenie focusout przycisku, aby ukryć kontener zawierający wiadomość
źródło
Jeśli Xmlhttprequest z obiektem blob nie jest opcją, możesz otworzyć plik w nowym oknie i sprawdzić, czy elementy eny są zapełniane w tym oknie z przerwami.
źródło
Ten przykład Java / Spring wykrywa koniec pobierania, w którym to momencie ukrywa wskaźnik „Ładowanie ...”.
Podejście: po stronie JS ustaw plik cookie o maksymalnym wieku wygaśnięcia wynoszącym 2 minuty i sprawdzaj co sekundę, czy plik cookie wygasł . Następnie strona serwera zastępuje ten plik cookie z wcześniejszym wiekiem ważności - zakończeniem procesu serwera. Po wykryciu wygaśnięcia pliku cookie w sondowaniu JS „Ładowanie ...” jest ukryte.
Strona JS
Strona Java / Spring Server
źródło
myCookie.setPath("/"); response.addCookie(myCookie);
Primefaces również korzysta z pobierania plików cookie
https://github.com/primefaces/primefaces/blob/32bb00299d00e50b2cba430638468a4145f4edb0/src/main/resources/META-INF/resources/primefaces/core/core.js#L458
źródło
Utwórz element iframe po kliknięciu przycisku / łącza i dołącz go do treści.
Utwórz element iframe z opóźnieniem i usuń go po pobraniu.
źródło