RE: [PHP-DEV] [PATCH] upload progress metter
| From: | David Enderson | Date: | Thu, 05 Jun 2003 22:29:38 +0000 |
| Subject: | RE: [PHP-DEV] [PATCH] upload progress metter | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-2191@lists.php.net to get a copy of this message | ||
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:
> 1. 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
>
> 3. 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!
>
> 4. copy the demo scripts to /upload directory
> 5. point your browser to the index.php script. upload some
> files. enjoy!
>
>
> Here is how it really works:
> 1. 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 zero
> + if (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, &header
> TSRMLS_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;
> }
>
>
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>