progressbar bij downloaden
ik downloadde een bestaande class en probeer om deze in te sluiten in een bestand om een pdf te downloaden. Het bestand om te downloaden werkt zonder de class. Maar nu met de class krijg ik de foutmelding "headers already sent by". Ook weet ik dat dit komt omdat er in één van die functies van de class al output komt via de flush().
Maar hoe kan ik dit oplossen of omzeilen?
Het download bestand:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
include('ProgressBar.class.php');
$bar = new ProgressBar();
$elements = 10000;
$bar->initialize($elements);
for($i=0;$i<$elements;$i++)
{
//doe wat tijd kost, in dit geval downloaden
$openen='http://www.ucro.be/hulpbestanden/folder.pdf';
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="downloaded.pdf"');
readfile($openen);
$bar->increase();
}
?>
include('ProgressBar.class.php');
$bar = new ProgressBar();
$elements = 10000;
$bar->initialize($elements);
for($i=0;$i<$elements;$i++)
{
//doe wat tijd kost, in dit geval downloaden
$openen='http://www.ucro.be/hulpbestanden/folder.pdf';
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="downloaded.pdf"');
readfile($openen);
$bar->increase();
}
?>
Dit is de class die ik vond
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<?php
class ProgressBar {
/**
* Constructor
*
* @param str $message Message shown above the bar eg. "Please wait...". Default: ''
* @param bool $hide Hide the bar after completion (with JavaScript).
* Default: false
* @param int $sleepOnFinish Seconds to sleep after bar completion. Default: 0
* @param int $barLength Length in pixels. Default: 200
* @param int $precision Desired number of steps to show. Default: 20. Precision will become $numElements when greater than $numElements. $barLength will increase if $precision is greater than $barLength.
* @param str $backgroundColor Color of the bar background
* @param str $foregroundColor Color of the actual progress-bar
* @param str $domID Html-Attribute "id" for the bar
* @param str $stepElement Element the bar is build from
*/
function ProgressBar($message='', $hide=false, $sleepOnFinish=0, $barLength=200, $precision=20,
$backgroundColor='#cccccc', $foregroundColor='blue', $domID='progressbar',
$stepElement='<div style="width:%spx;height:20px;float:left;"></div>'
){
//increase time limit
if(!ini_get('safe_mode')){
set_time_limit(0);
}
$this->hide = (bool) $hide;
$this->sleepOnFinish = (int) $sleepOnFinish;
$this->domID = strip_tags($domID);
$this->message = $message;
$this->stepElement = $stepElement;
$this->barLength = (int) $barLength;
$this->precision = (int) $precision;
$this->backgroundColor = strip_tags($backgroundColor);
$this->foregroundColor = strip_tags($foregroundColor);
if($this->barLength < $this->precision){
$this->barLength = $this->precision;
}
$this->StepCount = 0;
$this->CallCount = 0;
}
/**
* Print the empty progress bar
* @param int $numElements Number of Elements to be processed and number of times $bar->initialize() will be called while processing
*/
function initialize($numElements)
{
$numElements = (int) $numElements ;
if($numElements == 0){
$numElements = 1;
}
//calculate the number of calls for one step
$this->CallsPerStep = ceil(($numElements/$this->precision)); // eg. 1000/200 = 100
//calculate the total number of steps
if($numElements >= $this->CallsPerStep){
$this->numSteps = round($numElements/$this->CallsPerStep);
}else{
$this->numSteps = round($numElements);
}
//calculate the length of one step
$stepLength = floor($this->barLength/$this->numSteps); // eg. 100/10 = 10
//the rest is the first step
$this->rest = $this->barLength-($stepLength*$this->numSteps);
if($this->rest > 0){
$this->firstStep = sprintf($this->stepElement,$this->rest);
}
//build the basic step-element
$this->oneStep = sprintf($this->stepElement,$stepLength);
//build bar background
$backgroundLength = $this->rest+($stepLength*$this->numSteps);
$this->backgroundBar = sprintf($this->stepElement,$backgroundLength);
//stop buffering
ob_end_flush();
//start buffering
ob_start();
echo '<div id="'.$this->domID.'">'.
$this->message.'<br/>'.
'<div style="position:absolute;color:'.$this->backgroundColor.';background-color:'.$this->backgroundColor.'">'.$this->backgroundBar.'</div>' .
'<div style="position:absolute;color:'.$this->foregroundColor.';background-color:'.$this->foregroundColor.'">';
ob_flush();
flush();
}
/**
* Count steps and increase bar length
*
*/
function increase()
{
$this->CallCount++;
if(!$this->started){
//rest output
echo $this->firstStep;
ob_flush();
flush();
}
if($this->StepCount < $this->numSteps
&&(!$this->started || $this->CallCount == $this->CallsPerStep)){
//add a step
echo $this->oneStep;
ob_flush();
flush();
$this->StepCount++;
$this->CallCount=0;
}
$this->started = true;
if(!$this->finished && $this->StepCount == $this->numSteps){
// close the bar
echo '</div></div><br/>';
ob_flush();
flush();
//sleep x seconds before ending the script
if($this->sleepOnFinish > 0){
sleep($this->sleepOnFinish);
}
//hide the bar
if($this->hide){
echo '<script type="text/javascript">document.getElementById("'.$this->domID.'").style.display = "none";</script>';
ob_flush();
flush();
}
$this->finished = true;
}
}
}
?>
class ProgressBar {
/**
* Constructor
*
* @param str $message Message shown above the bar eg. "Please wait...". Default: ''
* @param bool $hide Hide the bar after completion (with JavaScript).
* Default: false
* @param int $sleepOnFinish Seconds to sleep after bar completion. Default: 0
* @param int $barLength Length in pixels. Default: 200
* @param int $precision Desired number of steps to show. Default: 20. Precision will become $numElements when greater than $numElements. $barLength will increase if $precision is greater than $barLength.
* @param str $backgroundColor Color of the bar background
* @param str $foregroundColor Color of the actual progress-bar
* @param str $domID Html-Attribute "id" for the bar
* @param str $stepElement Element the bar is build from
*/
function ProgressBar($message='', $hide=false, $sleepOnFinish=0, $barLength=200, $precision=20,
$backgroundColor='#cccccc', $foregroundColor='blue', $domID='progressbar',
$stepElement='<div style="width:%spx;height:20px;float:left;"></div>'
){
//increase time limit
if(!ini_get('safe_mode')){
set_time_limit(0);
}
$this->hide = (bool) $hide;
$this->sleepOnFinish = (int) $sleepOnFinish;
$this->domID = strip_tags($domID);
$this->message = $message;
$this->stepElement = $stepElement;
$this->barLength = (int) $barLength;
$this->precision = (int) $precision;
$this->backgroundColor = strip_tags($backgroundColor);
$this->foregroundColor = strip_tags($foregroundColor);
if($this->barLength < $this->precision){
$this->barLength = $this->precision;
}
$this->StepCount = 0;
$this->CallCount = 0;
}
/**
* Print the empty progress bar
* @param int $numElements Number of Elements to be processed and number of times $bar->initialize() will be called while processing
*/
function initialize($numElements)
{
$numElements = (int) $numElements ;
if($numElements == 0){
$numElements = 1;
}
//calculate the number of calls for one step
$this->CallsPerStep = ceil(($numElements/$this->precision)); // eg. 1000/200 = 100
//calculate the total number of steps
if($numElements >= $this->CallsPerStep){
$this->numSteps = round($numElements/$this->CallsPerStep);
}else{
$this->numSteps = round($numElements);
}
//calculate the length of one step
$stepLength = floor($this->barLength/$this->numSteps); // eg. 100/10 = 10
//the rest is the first step
$this->rest = $this->barLength-($stepLength*$this->numSteps);
if($this->rest > 0){
$this->firstStep = sprintf($this->stepElement,$this->rest);
}
//build the basic step-element
$this->oneStep = sprintf($this->stepElement,$stepLength);
//build bar background
$backgroundLength = $this->rest+($stepLength*$this->numSteps);
$this->backgroundBar = sprintf($this->stepElement,$backgroundLength);
//stop buffering
ob_end_flush();
//start buffering
ob_start();
echo '<div id="'.$this->domID.'">'.
$this->message.'<br/>'.
'<div style="position:absolute;color:'.$this->backgroundColor.';background-color:'.$this->backgroundColor.'">'.$this->backgroundBar.'</div>' .
'<div style="position:absolute;color:'.$this->foregroundColor.';background-color:'.$this->foregroundColor.'">';
ob_flush();
flush();
}
/**
* Count steps and increase bar length
*
*/
function increase()
{
$this->CallCount++;
if(!$this->started){
//rest output
echo $this->firstStep;
ob_flush();
flush();
}
if($this->StepCount < $this->numSteps
&&(!$this->started || $this->CallCount == $this->CallsPerStep)){
//add a step
echo $this->oneStep;
ob_flush();
flush();
$this->StepCount++;
$this->CallCount=0;
}
$this->started = true;
if(!$this->finished && $this->StepCount == $this->numSteps){
// close the bar
echo '</div></div><br/>';
ob_flush();
flush();
//sleep x seconds before ending the script
if($this->sleepOnFinish > 0){
sleep($this->sleepOnFinish);
}
//hide the bar
if($this->hide){
echo '<script type="text/javascript">document.getElementById("'.$this->domID.'").style.display = "none";</script>';
ob_flush();
flush();
}
$this->finished = true;
}
}
}
?>
Gewijzigd op 02/11/2013 16:40:01 door De Clercq Andy
Een header (het woord zegt het zelf) is een hoofding. 1 hoofding volstaat.
Een header() die binnenin een lus zit ( een while, een for, een do, ... ), kan dus nooit de bedoeling zijn.
Eigenlijk is het de bedoeling dat ik een pdf kan downloaden en ondertussen mijn bezoeker "bezig" houd.
Die class heb ik gevonden via google maar ik zoek hu hoe ik hem inpas.
Dt heb ik nu:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
include('ProgressBar.class.php');
$bar = new ProgressBar();
$elements = 10000;
$bar->initialize($elements);
for($i=0;$i<$elements;$i++)
{
//doe wat tijd kost, in dit geval downloaden
$bar->increase();
}
$openen='http://www.ucro.be/hulpbestanden/folder.pdf';
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="downloaded.pdf"');
readfile($openen);
?>
include('ProgressBar.class.php');
$bar = new ProgressBar();
$elements = 10000;
$bar->initialize($elements);
for($i=0;$i<$elements;$i++)
{
//doe wat tijd kost, in dit geval downloaden
$bar->increase();
}
$openen='http://www.ucro.be/hulpbestanden/folder.pdf';
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="downloaded.pdf"');
readfile($openen);
?>
Ook totaal andere oplossingen voor mijn probleem zijn welkom.
In ieder geval bedankt!
Stuur de browser de PDF, en die toont dan wel een balkje.
Tenslotte weet de browser (realtime) al hoeveel er binnen is en hoeveel er nog komt (door de headers van het bestand...).
Lijkt me veel veiliger, beter en makkelijker dan wat je nu doet.
Daarnaast: balkje-html, balkje-http-request, balkje-plaatje-tonen.... inmiddels is die PDF al lang binnen.