Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[PHP] screen output naar screen EN file om te downloaden.

Pagina: 1
Acties:

Onderwerpen


  • MarcHeijerman
  • Registratie: December 2007
  • Laatst online: 03-08 21:10
Hi all,

weer een vraag van mij....

Ik heb een php script die allerlei "html" tables laat zien. Nu zoek ik een manier om NA het uitvoeren van het script, de output ook naar een bestand wordt geschreven waardoor ik gebruik kan maken van een extra download button om het bestand ook op te slaan.

Ik heb nu een extra optie (dropdown) moeten aanmaken waardoor het script wordt aangeroepen en meteen als download wordt aangeboden, zonder de output op het scherm weer te geven.

Hier een voorbeeldje:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if(!isset($_SESSION)) {
        session_start();
}
$user=$_SESSION['user'];
$time = date("m.d.y");
$data = "";
$excel = include("/var/www/html/test/scripts/report.php");
  $fname = "/tmp/report"."_".$user."_".$time.".xls";
  $file = fopen($fname,"w+");
  fwrite($file,$excel);
  fclose($file);
  header('Content-Type: application/vnd.ms-excel');
  header('Content-Disposition: attachment; filename="'.basename($fname).'"');
  readfile($fname);
  unlink($fname);
$created=date("F j, Y, g:i a");
print "<br><br><b>Report created on: $created, created by: $user</b>";


Na het uitvoeren van deze code, wordt het report dus uitgevoerd, en metaan als bestand aangeboden. Ik wil dit dus eigenlijk in het report script zelf hebben.

Dus NA script, ook nog de optie om een bestand te downloaden.
Ik heb geprobeerd de bovenstaande code op verschillende manieren in report.php thuis te brengen, maar dan wordt er, OF niks op het scherm weergegeven, en alleen de download zichtbaar, OF alles wordt wel op het scherm weergegeven, maar dan zonder download.

Enig idee hoe ik dit kan oplossen ?

Mischien door een buffer toe te passen en deze naar een bestand te schrijven, en op het scherm weer te geven ?

Geen idee hoe dat dan zou moeten werken. Suggesties zijn van harte welkom, links naar tut's die ik hiervoor kan gebruiken uiteraard ook.

  • mithras
  • Registratie: Maart 2003
  • Niet online
Een request om iets te laten zien op het scherm is een ander request dan wat je doet met Content-Disposition: attachment. Ergo, dat kan zo niet. Het zijn twee verschillende requests die de browser achter elkaar moet uitvoeren.

Als je wilt dat toch direct na weergave de download wordt aangeboden, kan je wellicht de gebruiker eerst een link laten aanklikken om de pagina te laden voor de weergave-versie, om daarna automatisch een redirect te doen naar de download-versie. Een gebruiker ziet nog steeds de data op het scherm, maar krijgt ook de download voorgeschoteld.

  • dvdheiden
  • Registratie: Maart 2006
  • Laatst online: 24-11 17:41
Als je de output ook naar een file wilt wegschrijven en die wilt aanbieden als download kan je gebruik maken van de output buffer.

PHP:
1
2
3
4
5
6
7
8
ob_start(); //start output buffer

// output code hier, kan je gewoon echo'en

$output = ob_get_contents();
ob_end_clean(); //stop output buffer

//$output afdrukken en naar file schrijven


In je gewone window laat je dan het spul zien en dan eventueel popupje maken waarin die gelijk die download start.

[ Voor 13% gewijzigd door dvdheiden op 06-04-2012 09:30 ]


  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

Kun je d'r niet gewoon een linkje bij plaatsen dat naar dezelfde URL linkt, maar dan met een extra GET-parameter, die je in je script afvangt om ook de content-headers te schrijven?

Dus:

PHP:
1
2
3
4
5
6
7
8
9
if (isset($_GET['download']))
{
  header('Content-Type: application/vnd.ms-excel'); 
  header('Content-Disposition: attachment; filename="'.basename($fname).'"'); 
}

// knip rest

print '<a href="?download">Download</a>';


Edit: oh, dat zei mithras dus ook al. :+ Je kunt de ?download-call ook met een javascript-request issuen, door bij de onload de window.location aan te passen.

[ Voor 55% gewijzigd door CodeCaster op 06-04-2012 09:32 ]

https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...


  • MarcHeijerman
  • Registratie: December 2007
  • Laatst online: 03-08 21:10
mithras schreef op vrijdag 06 april 2012 @ 09:22:
Een request om iets te laten zien op het scherm is een ander request dan wat je doet met Content-Disposition: attachment. Ergo, dat kan zo niet. Het zijn twee verschillende requests die de browser achter elkaar moet uitvoeren.

Als je wilt dat toch direct na weergave de download wordt aangeboden, kan je wellicht de gebruiker eerst een link laten aanklikken om de pagina te laden voor de weergave-versie, om daarna automatisch een redirect te doen naar de download-versie. Een gebruiker ziet nog steeds de data op het scherm, maar krijgt ook de download voorgeschoteld.
Het is zo, dat als de pagina geladen wordt, er een aantal queries worden uitgevoerd, die totaal 20s in beslag nemen (vmrun), dus dan zou het 2 keer zo lang duren voordat de download klaar is, als ik dit goed begrijp

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Je bent dan 2x 20 seconden kwijt; 1x voor het parsen van de webpagina, plus daarna nog een keer voor het parsen van de output file.

  • MarcHeijerman
  • Registratie: December 2007
  • Laatst online: 03-08 21:10
CptChaos schreef op vrijdag 06 april 2012 @ 09:36:
Je bent dan 2x 20 seconden kwijt; 1x voor het parsen van de webpagina, plus daarna nog een keer voor het parsen van de output file.
precies, dus de gebruiken moet dan een extra 20s wachten op de download. Is er niet een manier om dit dus tegelijkertijd te doen.

Dus en de output naar het scherm, terwijl de output ook meteen naar een file wordt geschreven, mischien een onnozele opmerking, maar kan dit niet met een functie oid.

Wat ik bedoel is de functie dus naar een file laten schrijven, en de functie op het scherm laten weergeven.

  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

MarcHeijerman schreef op vrijdag 06 april 2012 @ 09:32:
[...]


Het is zo, dat als de pagina geladen wordt, er een aantal queries worden uitgevoerd, die totaal 20s in beslag nemen (vmrun), dus dan zou het 2 keer zo lang duren voordat de download klaar is, als ik dit goed begrijp
Deel het probleem op in kleinere stukken.

Gegeven het feit dat om een document weer te geven in de browser en om hetzelfde document te downloaden twee requests nodig zijn, zul je het document tijdelijk moeten opslaan. Dit doe je nu al, alleen verwijder je het meteen weer.

Dat verwijderen zul je dus moeten weglaten, waarna je de bestandsnaam meegeeft aan de download-url. Na het downloaden kun je het bestand wel verwijderen.

Zo ontstaat wel het risico dat de schijf zich vult met bestanden die alleen bekeken worden in de browser (hoe doe je dat eigenlijk met Excel-bestanden, je zit toch geen <table>'s te schrijven en dat stiekem .xls te noemen hè?) maar nooit gedownload worden; dit kun je bijvoorbeeld oplossen met een cronjob die alle bestanden ouder dan een dag verwijdert.

Er is een IE-only javascript (eigenlijk JScript)-aanroep, die de Save As-dialoog weergeeft voor de huidige pagina. Deze feature is door andere browsers nooit geïmplementeerd.

[ Voor 8% gewijzigd door CodeCaster op 06-04-2012 09:47 ]

https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...


  • MarcHeijerman
  • Registratie: December 2007
  • Laatst online: 03-08 21:10
CodeCaster schreef op vrijdag 06 april 2012 @ 09:41:
[...]

Deel het probleem op in kleinere stukken.

Gegeven het feit dat om een document weer te geven in de browser en om hetzelfde document te downloaden twee requests nodig zijn, zul je het document tijdelijk moeten opslaan. Dit doe je nu al, alleen verwijder je het meteen weer.

Dat verwijderen zul je dus moeten weglaten, waarna je de bestandsnaam meegeeft aan de download-url. Na het downloaden kun je het bestand wel verwijderen.

Zo ontstaat wel het risico dat de schijf zich vult met bestanden die alleen bekeken worden in de browser (hoe doe je dat eigenlijk met Excel-bestanden, je zit toch geen <table>'s te schrijven en dat stieken .xls te noemen hè?) maar nooit gedownload worden; dit kun je bijvoorbeeld oplossen met een cronjob die alle bestanden ouder dan een dag verwijdert.

Er was een IE-only javascript (eigenlijk JScript)-aanroep, die de Save As-dialoog weergaf voor de huidige pagina. Deze feature is door andere browsers nooit geïmplementeerd.
Stiekem .xls noemen :D, ehm hoe bedoel je dit precies...

Eerst maakt ik wel gebruik van tables "html" maar dat werd afgeraden, dus zijn het nu array's geworden, alleen snap ik nog steeds niet goed waarom je geen tables mag schrijven en het bestand als .xls mag opslaan, ik heb dit toevallig wel getest :D, en het werkt wel gewoon.

  • mithras
  • Registratie: Maart 2003
  • Niet online
MarcHeijerman schreef op vrijdag 06 april 2012 @ 09:39:
[...]'e


precies, dus de gebruiken moet dan een extra 20s wachten op de download. Is er niet een manier om dit dus tegelijkertijd te doen.

Dus en de output naar het scherm, terwijl de output ook meteen naar een file wordt geschreven, mischien een onnozele opmerking, maar kan dit niet met een functie oid.

Wat ik bedoel is de functie dus naar een file laten schrijven, en de functie op het scherm laten weergeven.
Je haalt nu een aantal verschillende dingen door elkaar. Even alles op een rijtje :)
  1. Je hebt een zware query die binnen één sessie meerdere keren wordt gebruikt
  2. Dus: je stopt het resultaat van de query in je cache, zodat je de 2e, 3e, 4e, ... keer altijd snel het resultaat hebt
  3. Je parsed het resultaat naar html
  4. Je wilt ook een download aanbieden, dus je redirect ook direct door naar een url die een Content-Disposition: attachment terugstuurt
Je hoeft niet per se de attachment te genereren en op je filesystem op te slaan, je moet op een gunstig moment in je proces het resultaat cachen. Dat kan direct je query resultaat zijn, of een verdere verwerkingsstap.

  • MarcHeijerman
  • Registratie: December 2007
  • Laatst online: 03-08 21:10
mithras schreef op vrijdag 06 april 2012 @ 09:44:
[...]
Je haalt nu een aantal verschillende dingen door elkaar. Even alles op een rijtje :)
  1. Je hebt een zware query die binnen één sessie meerdere keren wordt gebruikt
  2. Dus: je stopt het resultaat van de query in je cache, zodat je de 2e, 3e, 4e, ... keer altijd snel het resultaat hebt
  3. Je parsed het resultaat naar html
  4. Je wilt ook een download aanbieden, dus je redirect ook direct door naar een url die een Content-Disposition: attachment terugstuurt
Je hoeft niet per se de attachment te genereren en op je filesystem op te slaan, je moet op een gunstig moment in je proces het resultaat cachen. Dat kan direct je query resultaat zijn, of een verdere verwerkingsstap.
de "zware query" wordt eigenlijk maar 1 keer aangeroepen, alleen het duur helaas gewoon lang voordat alle resultaten beschikbaar zijn. Ik schrijf alle resultaten weg naar 1 bestand waarna ik php icm bash verschillende resultaten laat generen uit dat ene bestand en die worden vervolgens op het scherm weer gegeven.

voorbeeld:

PHP:
1
2
3
shell_exec("vmrun -h <host> -u <user> -p <password(niet plaintext, maar uit file)> list > file");
// Hierna laat ik verschillende commands lost op dit ene bestand
// php matched op bepaalde strings, omgevingen, .vmx files etc...


Dus ik weet niet of het veel zin heeft die ene vmrun in de cache op te slaan.

  • mithras
  • Registratie: Maart 2003
  • Niet online
Het idee blijft hetzelfde hoor ;) Slechts de methode van cachen (file system, sessie, memcache, apc etc) en het formaat (serialized php, blob, ...) moet je zelf bedenken en aan de hand van jouw specifieke situatie bepalen.

  • MarcHeijerman
  • Registratie: December 2007
  • Laatst online: 03-08 21:10
Ok, bedankt voor de reacties, ik ga met de nieuwe info weer even verder spelen en kijken of ik nog iets werkends kan krijgen voor het einde van de dag haha

  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

MarcHeijerman schreef op vrijdag 06 april 2012 @ 09:44:
[...]


Stiekem .xls noemen :D, ehm hoe bedoel je dit precies...

Eerst maakt ik wel gebruik van tables "html" maar dat werd afgeraden, dus zijn het nu array's geworden, alleen snap ik nog steeds niet goed waarom je geen tables mag schrijven en het bestand als .xls mag opslaan, ik heb dit toevallig wel getest :D, en het werkt wel gewoon.
Het mag wel, en het werkt, maar ik vind het nogal een hack en heb het regelmatig mis zien gaan. Voor een paar platte tabellen zonder opmaak en colspans/rowspans zal het inderdaad wel werken, maar er zijn legio alternatieven die wel netjes een "echte" .xls schrijven.

Op die manier kun je 't alleen niet meer in je browser weergeven, en zal het bestand altijd als download worden aangeboden. :P

https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...


  • MarcHeijerman
  • Registratie: December 2007
  • Laatst online: 03-08 21:10
CodeCaster schreef op vrijdag 06 april 2012 @ 09:54:
[...]

Het mag wel, en het werkt, maar ik vind het nogal een hack en heb het regelmatig mis zien gaan. Voor een paar platte tabellen zonder opmaak en colspans/rowspans zal het inderdaad wel werken, maar er zijn legio alternatieven die wel netjes een "echte" .xls schrijven.

Op die manier kun je 't alleen niet meer in je browser weergeven, en zal het bestand altijd als download worden aangeboden. :P
Top bedankt, ik ga je link zeker even doornemen :D

  • MarcHeijerman
  • Registratie: December 2007
  • Laatst online: 03-08 21:10
Ik ga deze 2 eens goed doornemen:

ExcelWriterXML
php_writeexcel

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Ik zou dan eerder neigen naar PEAR: deze dus.
Dat is makkelijk te installeren, gebruik ervan zal opzich ook geen groot probleem zijn denk ik.

  • Pmleader
  • Registratie: Februari 2012
  • Laatst online: 11-11 12:47
Zelf heb ik voor een bijna gelijk probleem dompdf( http://code.google.com/p/dompdf/) gebruikt.

ik denk dat jij dat ook wel kan gebruiken in deze situatie

  • Manuel
  • Registratie: Maart 2008
  • Laatst online: 24-11 08:37
Pmleader schreef op vrijdag 06 april 2012 @ 11:29:
Zelf heb ik voor een bijna gelijk probleem dompdf( http://code.google.com/p/dompdf/) gebruikt.

ik denk dat jij dat ook wel kan gebruiken in deze situatie
Wat heeft een PDF generator met een Excel bestand te maken? Output afvangen kan gewoon met de ingebakken ob_* functies, daar is geen extra pakket voor nodig.

  • Pmleader
  • Registratie: Februari 2012
  • Laatst online: 11-11 12:47
Manuel schreef op vrijdag 06 april 2012 @ 11:37:
[...]

Wat heeft een PDF generator met een Excel bestand te maken? Output afvangen kan gewoon met de ingebakken ob_* functies, daar is geen extra pakket voor nodig.
mijn excuses ik heb in geen van de berichten van de topic starter gelezen dat het een Excel bestand MOEST zijn...

hij heeft wel meerdere keren naar een .xls gerefereerd maar niet 1 keer aangegeven dat dat een vereiste was...

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Manuel schreef op vrijdag 06 april 2012 @ 11:37:
Wat heeft een PDF generator met een Excel bestand te maken? Output afvangen kan gewoon met de ingebakken ob_* functies, daar is geen extra pakket voor nodig.
Wellicht komt er nu dus wel een mogelijkheid bij om de output in PDF te zetten... ;)
Snap niet waarom alternatieven altijd de grond in geboord moeten worden...
Daarnaast vraag ik me af of je de vraag van de TS wel snapt. True, ob_* functies zijn om output te bufferen (waar zou de ob anders voor staan denk je? ;)), maar aan het einde van het PHP-script wordt dat gewoon weer verwijderd, heb je dus niets aan in dit geval, tenzij je er iets mee doet.

Daarnaast is de bestandsindeling van Excel of PDF anders dan HTML, dus aan buffering alleen heb je weinig.

[ Voor 107% gewijzigd door CH4OS op 06-04-2012 12:30 ]


  • Pmleader
  • Registratie: Februari 2012
  • Laatst online: 11-11 12:47
CptChaos schreef op vrijdag 06 april 2012 @ 11:52:
Wellicht komt er nu dus wel een mogelijkheid bij om de output in PDF te zetten... ;)
Dat was precies mijn inzet, meerdere mogelijkheden.
Aangezien .pdf algemeen geaccepteerd is voor facturen en rapporten, is het niet eens zo'n gek idee om het toe te passen.

Uiteraard als het tabellen moeten worden die men later nog kan bewerken is .pdf niet toe te passen.

  • MarcHeijerman
  • Registratie: December 2007
  • Laatst online: 03-08 21:10
Ik ben nu bezig een appart php scriptje te bouwen die ongeveer hetzelfde doet als de webpage, alleen alles meteen naar een bestand wegschrijft, waarna ik een download link laat zien op de webpage, stiekem :P even 2 seconden extra laten slapen zodat ik zeker weet dat het achtergrond script zijn werk ook heeft gedaan, en de download dus beschikbaar is.

Schijnt goed te werken, alleen zit ik nu met de tekst opmaak.
Hoe kan ik bijvoorbeeld bold, cursief, en kleur toevoegen aan de data die ik weg schrijf ?
Ik maak nu dus geen gebruik van html, dus <font><b> etc gaat nu niet werken. Ik ben de online php manual aan het lezen, maar ik kan niet direct iets zinnigs vinden over tekst opmaak zonder html.

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

MarcHeijerman schreef op vrijdag 06 april 2012 @ 12:59:
Schijnt goed te werken, alleen zit ik nu met de tekst opmaak.
Hoe kan ik bijvoorbeeld bold, cursief, en kleur toevoegen aan de data die ik weg schrijf ?
Ik maak nu dus geen gebruik van html, dus <font><b> etc gaat nu niet werken. Ik ben de online php manual aan het lezen, maar ik kan niet direct iets zinnigs vinden over tekst opmaak zonder html.
Ik zou eerst het script zelf maken, zodat het PDF-bestanden máákt. Daarna kun je in de documentatie bekijken hoe je de opmaak aan kan passen.

  • Manuel
  • Registratie: Maart 2008
  • Laatst online: 24-11 08:37
CptChaos schreef op vrijdag 06 april 2012 @ 11:52:
[...]

Wellicht komt er nu dus wel een mogelijkheid bij om de output in PDF te zetten... ;)
Snap niet waarom alternatieven altijd de grond in geboord moeten worden...
Daarnaast vraag ik me af of je de vraag van de TS wel snapt. True, ob_* functies zijn om output te bufferen (waar zou de ob anders voor staan denk je? ;)), maar aan het einde van het PHP-script wordt dat gewoon weer verwijderd, heb je dus niets aan in dit geval, tenzij je er iets mee doet.

Daarnaast is de bestandsindeling van Excel of PDF anders dan HTML, dus aan buffering alleen heb je weinig.
'Wellicht'. Wellicht besluit de TS straks dat hij het ook graag naar een CSV, XML + XSLT, HTML, TXT of wat dan ook. Het maakt niet uit in welk formaat je het wilt omzetten, je hebt die ob_* functies nodig om de output af te vangen. Dat staat helemaal los van hoe je het wilt laten weergeven.

Om de TS zijn vorige reactie uit een ander topic er even bij te pakken:
MarcHeijerman schreef op maandag 26 maart 2012 @ 15:36:
[..]
statistieken:
aantal esxhosts
aantal vms
aantal vms per esxhost
berekening met een run rate gebaseerd op een aantal variabelen als: vmbuilds in queue, completed etc..
wordt best een uitgebreid iets.
Nu zie ik wel een mogelijkheid voor een PDF bestand, daar ging het mij ook niet om, maar zo zie ik ook mogelijkheden voor output in andere formaten. Het gaat mij er om dat je met dit kleine beetje data al zeker bent dat je een PDF wilt severen, je weet nog niet eens of de data aanpasbaar moet kunnen zijn.

Dat je allerlei formaten kunt uitpoepen met behulp van / via PHP is wel bekend, alleen moet je ergens beginnen. Ik ben van mening dat hij begint bij het begin, net zoals dat hij eerst hebt leren lopen voordat hij kon rennen.
Pmleader schreef op vrijdag 06 april 2012 @ 11:40:
mijn excuses ik heb in geen van de berichten van de topic starter gelezen dat het een Excel bestand MOEST zijn...

hij heeft wel meerdere keren naar een .xls gerefereerd maar niet 1 keer aangegeven dat dat een vereiste was...
Ik was een beetje vel, my bad. :) Ik heb het ook nergens gezien, maar ik ga ervan uit dat de TS toch om een reden een Excel-bestand kiest in plaats van een simpel HTML bestand met een stylesheet.

  • MarcHeijerman
  • Registratie: December 2007
  • Laatst online: 03-08 21:10
Heb nu plaintext de output door geschopt naar een bestand:

Ik heb een los script dat de zelfde query uitvoert als de pagina, alleen heb ik uiteraard al het html weggelaten. Dit script heb ik toegevoegd aan de report page.

Tijdens het opvragen van de report page wordt dit script gestart:
PHP:
1
2
3
exec("php /<path>/<to>/<script> &> /dev/null  // Er wordt nu niet meer gewacht op de output, zonder &> wel.

// pagina code

nu worden er door het non html script 2 bestanden gegenereerd voor 2 verschillende environments, deze worden samengevoegd, en er wordt een download link weer gegeven op de report page, nadat de pagina geladen is.

Geen 2 keer wacht tijd dus. Het hoeft verder niet moeilijk te zijn, het bestand kan simpel in Excel geopend worden en voor het eindresultaat is dit meer dan genoeg.

Bedankt voor de reacties, en de linkjes, heeft allemaal geholpen.

Thanks
Pagina: 1