Moi,
Ongelmana on http://www.aplusdesign.com.au/blog/jquery-ajax-loader-spinner/ scripti, jota on muokattu vähän alkuperäisestä, mutta kuitenkin... scripti tulee siis näkyviin, kun pdf -tiedoston lataus aloitetaan sivustolla.
Latauspalkki tulee kyllä oikein näkyviin, mutta se ei lähde sivulta pois, kun php:n headerit on käyty läpi. Sivun pohjana on Codeigniter, jossa on käytetty valmista download_helper.php -luokkaa tiedoston lataukseen.
Ongelma on, että latauksen jälkeen ajaxLoaderFunction('a', 'click'); ei enään voida ladata ja latauspalkki jää ”rullaamaan” sivustolle. Miten tämän saisi niin, että esimerkiksi kun php:n exit($data); on ajettu, niin voitaisiin kutsua removeLoaderBar(id); -funktiota ja näin javascript voitaisiin poistaa. Vai saisiko tämän tehty getAllResponseHeaders() -funktiolla jotenkin?
headerin jälkeen kun ei pysty enään tekemään uudelleenohjausta, laittamaan echon sisään javascriptiä jne.
Eli..
Scripti:
//Ladataan aina siirtymien yhteydessä $(document).ready( function() { ajaxLoaderFunction('a', 'click'); });
//ajax_loader_script.js function ajaxLoaderFunction(id, clickEvent){ $(id).on(clickEvent, function() { new ajaxLoader(this); }); } function removeLoaderBar(el){ this.container = $(el); var overlay = this.container.children(".ajax_overlay"); if (overlay.length) { overlay.fadeOut(function() { overlay.remove(); }); } } function ajaxLoader(el) { this.container = $(el); this.init = function() { var container = this.container; var overlay = $('<div></div>').css({ 'background-color' : '#D8D8D8', 'opacity' : '0.2', 'filter' : 'alpha(opacity=20)', 'width' : '100%', 'height' : '100%' }).addClass('ajax_overlay'); var loaderBar = $('<p></p>').css({ 'position' : 'absolute', 'top' : '0px', 'left' : '0px', 'bottom' : '0px', 'right' : '0px' }).addClass('ajax_overlay'); container.append( loaderBar.append( $('<p></p>').addClass('ajax_loader').append( overlay.append($('<div></div>')).fadeIn(800).click(false).css('cursor', 'wait') ) ) ); }; removeLoaderBar(el); this.init(); }
//download helper lyhyesti if (strpos($_SERVER['HTTP_USER_AGENT'], "MSIE") !== FALSE) { header('Content-Type: "'.$mime.'"'); header('Content-Disposition: attachment; filename="'.$filename.'"'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header("Content-Transfer-Encoding: binary"); header('Pragma: public'); header("Content-Length: ".strlen($data)); } else { header('Content-Type: "'.$mime.'"'); header('Content-Disposition: attachment; filename="'.$filename.'"'); header("Content-Transfer-Encoding: binary"); header('Expires: 0'); header('Pragma: no-cache'); header("Content-Length: ".strlen($data)); } exit($data); //tämän jälkeen jotenkin removeLoaderBar(id);
En käsitä miksi jaksat edes nähdä vaivaa näin mitättömän asian eteen.
Eikö riitä, että selain itse ilmoittaa latauksen päättyneen?
Eli ymmärtäisin, jos kyseessä olisi ajaxilla toteutettu uploadaus toiminto, mutta lataus... voisihan tuon tehdä vaikka tallentamalla käyttäjän $_SESSION -muuttujaan yksilöity muuttuja latauksen loputtua (jota tarkkailet säännöllisesti siellä lataussivulla), joka vastaa tiedoston id-numeroa/nimeä, tällöinkin ongelmaksi muodostuu se, että käyttäjä lataa samaa tiedostoa kerralla useamman kuin yhden kappaleen.
etkö voi vain kutsua $(".ajax_overlay").remove()?
groovyb kirjoitti:
etkö voi vain kutsua $(".ajax_overlay").remove()?
Voin kutsua, mutta missä kutsun? Se tässä ongelmana on.
no eikös sitä php sivulle voi lisätä javascriptia ihan
<?php echo "<script> alert('this is a javascript code')</script>"; ?>
jos kyse on siis siitä että haluat javascriptia kutsuttavan php:llä luodussa sivussa.
groovyb, etkö tosiaan voi lukea kysymystä? Tiivistelmä: Miten saa linkistä aukeavan PDF:n latauduttua ajettua JS-koodia sillä sivulla, jolla linkkiä klikattiin?
JS-koodia ei voi upottaa ladattavaan tiedostoon, koska tiedosto ei selvästikään ole HTML-tiedosto eikä sitä ole tarkoitus avata selaimella vaan tallentaa (otsikko "Content-Disposition: attachment").
Tiedoston lataaminen iframen kautta ei auta, koska ainakin Firefoxissa iframen onload-käsittelijä ajetaan heti, kun selaimelle selviää, että tiedosto halutaan tallentaa eikä näyttää suoraan.
Latauksen tilan kyseleminen palvelimelta ei käytännössä toimi, koska PHP:llä ei ole kunnollista tapaa tietää, milloin lataus on valmis. Datan tulostus (echo) on valmis käytännössä heti, vaikka tietoa vasta aletaan siirtää verkkoon, ja toisaalta selain ei ilmoita valmistumisesta eikä kokeilemani "Connection: close" ja connection_status()-arvon tarkkailu toiminut ainakaan minun palvelimellani vaan skripti jäi ikuiseen silmukkaan.
Viimeinen purkkaratkaisu on ensin ladata tiedosto taustalla ja avata tallennusdialogi jälkikäteen. Tiedon voi periaatteessa ladata AJAX-pyynnöllä ja antaa ladattavaksi data-URIlla, mutta tässä täytyy kikkailla tiedon muodon kanssa eikä tallentamisen pakottaminen taida onnistua. Toisena vaihtoehtona voisi tulla kyseeseen jokin Flash-sovellus, mutta pitää muistaa, ettei sellainen toimi kaikilla. Kolmas vaihtoehto on luopua koko tarpeettomasta ideasta: kai nyt kaikista selaimista näkee muutenkin, miten lataus etenee ja milloin se on valmis.
Hyviä vinkkejä tuli, mutta luovun tosiaan koko ratkaisusta sen hankaluuden vuoksi.
Ainut hyvä ratkaisu tähän olisi tainnut tosiaan olla Lebe80:n sessioon tyyppinen ratkaisu yhdistettynä Metabolixin ehdottamaan Ajax-pyyntöön. how-do-i-display-a-message-after-a-file-has-been-downloaded
Query kirjoitti:
Ainut hyvä ratkaisu tähän olisi tainnut tosiaan olla Lebe80:n sessioon tyyppinen ratkaisu yhdistettynä Metabolixin ehdottamaan Ajax-pyyntöön.
Luitko viestiäni kunnolla? Selitin, miksi kyseinen ratkaisu ei toimi: PHP-koodin suoritus ei vielä tarkoita, että tiedosto olisi siirretty, joten PHP-koodin suoritus voi kestää 0,01 sekuntia (jolloin miettimäsi koodi jo väittäisi, että lataus on valmis), vaikka lataus kestäisi oikeasti 100 sekuntia.
Aihe on jo aika vanha, joten et voi enää vastata siihen.