I also developed upload status capability for my company that works very
similarly to yours. I am currently working on integrating the changes I
made into a patch for 4.3.2 for members of this list to evaluate (I
originally made the upgrade to 4.1.2).
I see you came to the same conclusion I did, that the easiest way to
pass information seemed to be through the use of temporary files. I was
hoping that once I submitted my patch that someone on this list might
have a better suggestion like direction on using shared memory or
something.
--David
-----=+=-----
David Enderson
Programmer
Digital IMS
402.437.0137
denderson@digitalims.com
Hi,
To make a long story short, I needed an upload progress
metter, so the users will something while their huge files
are uploaded to the server. I searched the net but only found
for ASP, so I wrote one. Unfortunatly PHP needs a little
patch to be willing to do this ...Here is how it works:
- apply patch to php and recompile php (and apache if
needed) 2. add something like this to http.conf#for php-upload-progress-bar
<Directory /www/htdocs/upload>
php_value upload_metter 1
php_value upload_metter_dir "/tmp/uploadbar"
</Directory>
- This will activate the progress metter for /upload
- And will tell it to write progress informations to /tmp/uploadbar
mkdir /tmp/uploadbar; chmod 777 /tmp/uploadbar
I have to say that 0777 and /tmp are not the best choises from a
security point of view. you should find a better place!copy the demo scripts to /upload directory
point your browser to the index.php script. upload some
files. enjoy!Here is how it really works:
- index.php will generate and uniq ID for each upload. This
ID will be used to track the progress and report it. 2. a
special field named 'UPLOAD_METTER_ID' is used to store this
ID. make sure this field is BEFORE any 'file' fields. put it
at the begining of the form! 3. onSubmit()-ing the form a
small window will open where the progress.php will display
the actual progress bar. 4. php will check the value of
'upload_metter' and 'upload_metter_dir' configuration options
and the presence and value of 'UPLOAD_METTER_ID' field 5. the
progress file is stored in the directory named by 'upload_metter_dir'
and the vlaue of UPLOAD_METTER_ID field is used as the
name of the file 6. progress information is updated once a
second by the php engine 7. script progress.php will use the
ID field which it receives as a parameter to locate the
associated progress-file and read progress information from
it. then generate the little proggress bar 8. the progress
bar will 'refresh' about once a second, depending on how fast
the network is going 9. when upload is completed, the
progress.php script will remove the progress file, and close
the pop-up window.NOTE: there is a good chance that this progress files will
not be deleted from various reasons (client don't have JS
activated, or it closes the popup while data is still
uploaded, etc...), so there is a need to periodically cleanup
the directory of old files.What the PATCH does:
- adding 2 new cinfiguration options to PHP: upload_metter
and upload_metter_dir- in rfc1867.c: changes rfc1867_post_handler() to make some
calls to a newly defined function that will update the
progress metter:
update_progress_metter()- in turn it calls update_progress_metter_file(), trying its
best not to update the file more than once a second.I have tested it with php-4.2.3 and 4.3.2. atch for php-4.3.2
is attached. a patch for 4.2.3 is also available. basically
is the same thing.the rest of the files and a live demo can be found here:
http://pdoru.from.ro/Please let me know if you have any problems/suggestions :-)
Best regards,
Doru Petrescu
Senior Software Engineer
Astral Telecom Bucuresti
diff -rubB orig/php-4.3.2/main/main.c php-4.3.2/main/main.c
--- orig/php-4.3.2/main/main.c Thu May 22 01:54:38 2003
+++ php-4.3.2/main/main.c Thu Jun 5 22:58:46 2003
@@ -345,7 +345,9 @@
STD_PHP_INI_BOOLEAN("file_uploads",
"1", PHP_INI_SYSTEM, OnUpdateBool,
file_uploads, php_core_globals,
core_globals)
STD_PHP_INI_ENTRY("upload_max_filesize", "2M",
PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateInt,
upload_max_filesize, php_core_globals,
core_globals)
STD_PHP_INI_ENTRY("post_max_size",
"8M", PHP_INI_SYSTEM|PHP_INI_PERDIR,
OnUpdateInt, post_max_size,
sapi_globals_struct,sapi_globals)
- STD_PHP_INI_ENTRY("upload_tmp_dir",
NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty,
upload_tmp_dir, php_core_globals,
core_globals)
- STD_PHP_INI_ENTRY("upload_tmp_dir",
NULL, PHP_INI_ALL, OnUpdateStringUnempty,
upload_tmp_dir,
php_core_globals, core_globals)STD_PHP_INI_ENTRY("upload_metter","0", PHP_INI_ALL, OnUpdateBool,
upload_metter, php_core_globals,
core_globals)
STD_PHP_INI_ENTRY("upload_metter_dir",NULL, PHP_INI_ALL, OnUpdateStringUnempty,
upload_metter_dir, php_core_globals,
core_globals)STD_PHP_INI_ENTRY("user_dir",
NULL, PHP_INI_SYSTEM, OnUpdateString,
user_dir,
php_core_globals, core_globals)
STD_PHP_INI_ENTRY("variables_order", NULL,
PHP_INI_ALL, OnUpdateStringUnempty,
variables_order, php_core_globals, core_globals)
diff -rubB orig/php-4.3.2/main/php_globals.h
php-4.3.2/main/php_globals.h
--- orig/php-4.3.2/main/php_globals.h Sun May 18 13:22:16 2003
+++ php-4.3.2/main/php_globals.h Thu Jun 5 22:56:57 2003
@@ -133,6 +133,8 @@
zend_bool modules_activated;zend_bool file_uploads;
zend_bool upload_metter;
char * upload_metter_dir;
zend_bool during_request_startup;
diff -rubB orig/php-4.3.2/main/rfc1867.c php-4.3.2/main/rfc1867.c
--- orig/php-4.3.2/main/rfc1867.c Sat May 24 00:37:16 2003
+++ php-4.3.2/main/rfc1867.c Thu Jun 5 22:59:45 2003
@@ -676,6 +678,81 @@
return out;
}+typedef struct _Xdata {
- int time_start;
- int time_last;
- int speed_average;
- int speed_last;
- int bytes_uploaded;
- int bytes_total;
- int files_uploaded;
- char progress[1024];
+} Xdata;+static void update_progress_metter_file(Xdata *X)
+{
- int eta,s;
- FILE *F = VCWD_FOPEN(X->progress, "wb");
- s = X->speed_average; if (s < 1) s=1;
- eta = (X->bytes_total - X->bytes_uploaded) / s;
- if (F) {
- fprintf(F,
"time_start=%d\ntime_last=%d\nspeed_average=%d\nspeed_last=%d
nbytes_uploaded=%d\nbytes_total=%d\nfiles_uploaded=%d\neta=%d\n",X->time_start, X->time_last,X->speed_average, X->speed_last, X->bytes_uploaded,
X->bytes_total, X->files_uploaded, eta
- );
- fclose(F);
- }
- sapi_module.sapi_error(E_NOTICE, "metter: read %d of %d",
+SG(read_post_bytes), SG(request_info).content_length ); }+static void update_progress_metter(Xdata *X, int read, int total) {
- int d,dt,dtx;
- int bu;
- int sp;
- if (!X->time_start) {
X->time_start = X->time_last = time(NULL);X->bytes_total = total;X->bytes_uploaded = read;X->speed_average = X->speed_last = X->bytes_uploaded;update_progress_metter_file(X);return;- }
- dt = time(NULL) - X->time_last;
- d = read - X->bytes_uploaded;
- if (dt < 1) {
if (read < total)return; // avoid divide by zeroif (d < 1)- return;
dt = 1;- }
- sp = d/dt;
- X->bytes_uploaded = read;
- X->time_last = time(NULL);
- dtx = X->time_last - X->time_start; if (dtx
< 1) dtx = 1;- X->speed_average = X->bytes_uploaded / dtx;
- X->speed_last = sp;
- update_progress_metter_file(X);
+}/*
- The combined READER/HANDLER
@@ -693,6 +770,10 @@
zval *array_ptr = (zval *) arg;
FILE *fp;
zend_llist header;
Xdata X;
int progress_metter=0;
bzero(&X,sizeof(X));
if (SG(request_info).content_length > SG(post_max_size)) {
sapi_module.sapi_error(E_WARNING, "POST
Content-Length of %d bytes exceeds the limit of %d bytes",
SG(request_info).content_length, SG(post_max_size)); @@
-753,6 +838,9 @@
zend_llist_clean(&header);if (!multipart_buffer_headers(mbuff, &headerTSRMLS_CC)) {
if (progress_metter)update_progress_metter( &X,
+SG(read_post_bytes), SG(request_info).content_length );
SAFE_RETURN;
}@@ -806,6 +894,35 @@
max_file_size = atol(value);
}
if (!strcmp(param,"UPLOAD_METTER_ID") && PG(upload_metter) && PG(upload_metter_dir)) {
char *c,*v = estrdup(value);for (c=v;*c;c++) {if ( (*c >= '0' && *c <= '9') ||(*c >= 'a'&& *c <= 'z') ||
(*c >= 'A' && *c <= 'Z') ||*c == '.' || *c == '_' ||*c == ',' || *c == '@' ||*c == '-' || *c == '%') {}else{*c=0;break;}}if (v && *v) {if (strlen(v) > 64) v[64]=0;progress_metter=1;snprintf(X.progress,1000,"%s/%s", PG(upload_metter_dir), v);
}efree(v);}efree(param); efree(value); continue;@@ -831,6 +948,9 @@
SAFE_RETURN;
}
if (progress_metter)update_progress_metter( &X, SG(read_post_bytes),
SG(request_info).content_length );
X.files_uploaded++;if (!skip_upload) { /* Handle file */ fp =php_open_temporary_file(PG(upload_tmp_dir), "php",
&temp_filename TSRMLS_CC); @@ -872,6 +992,10 @@
} else {
total_bytes += wlen;
}
if (progress_metter)update_progress_metter( &X,
+SG(read_post_bytes), SG(request_info).content_length );
}
}
fclose(fp);
@@ -1047,6 +1173,10 @@
efree(param);
}
}
if (progress_metter) update_progress_metter( &X,
SG(read_post_bytes),
+SG(request_info).content_length );SAFE_RETURN;
}