好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

PHP文件上传带进度条

实现篇:

一般情况,用php实现上传进度条就下面两种方法:

1.apc扩展(作者是php教程的创始人,5.2后php已经加入apc扩展)

2.pecl扩展模块 uploadprogress

不论是apc还是uploadprogress,都需要编译源码,因为原有的php函数根本不可能读取到临时文件夹里的东西,下面来看如何使用以及关键的代码:apc实现方法:

1.安装apc

2.配置php.ini,设置参数 apc.rfc1867=1

3.关键代码:

if  ( $_server [ 'request_method' ] == ‘post’) {   //上传请求   $status  = apc_fetch(’upload_’ .  $_post [ 'apc_upload_progress' ]);  $status [ 'done' ] = 1; //开源代码phpfensi.com   echo  json_encode( $status );   //输出给用户端页面里的ajax调用,相关文档请自己寻找   exit ;  }  elseif  (isset( $_get [ 'progress_key' ])) {    //读取上传进度   $status  = apc_fetch(’upload_’. $_get [ 'progress_key' ]);  echo  json_encode( $status );  exit ;  } 

uploadprogress实现方法:

1.使用pecl 安装uploadprogress

2.php.ini里面设置 uploadprogress.file.filename_template = [/tmp/upd_%s.txt]

3.关键代码如下:

if ( $_server [ 'request_method' ]==’post’) {  if  ( is_uploaded_file ( $_files [ 'upfile' ][ 'tmp_name' ])) {  $upload_dir  = ‘your_path/’;  $ext         =  strrchr ( $_files [ 'video' ][ 'name' ], ‘.’);  $sessid      =  $_post [ 'upload_identifier' ] ;  $tmpfile     =  $upload_dir  .  $sessid ;  $sessfile    =  $upload_dir  .  $sessid  . $ext ;  if  (move_uploaded_file( $_files [ 'upfile' ][ 'tmp_name' ], $tmpfile )) {  //上传成功   }  }   }  elseif  (! empty empty ( $_get [ 'sessid' ])) {  header(]expires: mon, 26 jul 1997 05:00:00 gmt]);  header(]last-modified: ] .  gmdate (]d, d m y h:i:s]) . ] gmt]);  header(]cache-control: no-store, no-cache, must-revalidate]);  header(]cache-control: post-check=0, pre-check=0′, false);  header(]pragma: no-cache]);  header(]content-type:text/html;charset=utf-8′);  $unique_id  =  $_get [ 'sessid' ];  $uploadvalues  = uploadprogress_get_info( $unique_id );  if  ( is_array ( $uploadvalues )) {  echo  json_encode( $uploadvalues );  }  else  {  //读取进度失败,另外处理逻辑   }  } 

二.原理篇

注意上一篇中的红色函数,下载到uploadprogress1.0.1进行源码分析,在代码中作了注释,代码如下:

static  void uploadprogress_file_php_get_info(char * id, zval * return_value)  {  char s[1024];  char * filename;  char * template;  file *f;  tsrmls_fetch();  template = ini_str(]uploadprogress.file.filename_template]); <<这里读取设置好的模板  if  ( strcmp (template, []) == 0)  {  return ;  }  else  {  filename = uploadprogress_mk_filename( id, template );<<<存在的话,会创建  if  (!filename)  return ;  f = vcwd_fopen(filename, [rb]);  if  (f) {  array_init(return_value);  while  (  fgets (s, 1000, f) ) {<<<从流中读取一字符串 *s结果数据的首地址;1000-1:一次读入数据块的长度,其默认值为1k,即1024;f文件指针  char *k, *v, *e;  int index = 0;  e =  strchr (s,’='); <<<查找字符串s中首次出现字符=的位置  if  (!e)  continue ;  *e = 0;  /* break the line into 2 parts */   v = e+1;  k = s;  /* trim spaces in front of the name/value */   while  (*k && *k <= 32) k++;  while  (*v && *v <= 32) v++;  /* trim spaces everywhere in the name */   for  (e=k; *e; e++)  if  (*e <= 32) { *e = 0;  break ; }  /* trim spaces only at the end of the value */   /* http://111cn.net */   //for (e=v; *e; e++) if (*e <= 32) { *e = 0; break; }   if  (v != null) {<<<当文件有内容时  for  (index =  strlen (v); index > 0; index–) {  if  (v[index] > 32)  break ;<<<累计  v[index] = 0;  }  }  add_assoc_string( return_value, k, v, 1 );  }  fclose(f);  }  if  (filename) efree(filename);  return ;  }  } 

在源码中还能发现如下代码:

php_minit_function(uploadprogress)  {  register_ini_entries();  php_rfc1867_callback = uploadprogress_php_rfc1867_file;  return  success;  } 

在minit中修改了php_rfc1867_callback,抽取uploadprogress_php_rfc1867_file的关键代码,代码如下:

upload_id = emalloc( strlen (*e_data->value) + 1);  strcpy(upload_id, *e_data->value);  progress->upload_id = upload_id;  progress->time_last  = time(null);  progress->speed_average  = 0;  progress->speed_last     = 0;  progress->bytes_uploaded = read_bytes;  progress->files_uploaded = 0;  progress->est_sec        = 0;  progress->identifier = uploadprogress_mk_filename(upload_id, template);<<<在指定的模板位置放下了临时文件  progress->identifier_tmp = emalloc( strlen ( progress->identifier) + 4);  sprintf( progress->identifier_tmp, [%s.wr], progress->identifier );  

查看更多关于PHP文件上传带进度条的详细内容...

  阅读:90次