php文件上传之原理分析与上传类代码

今天研究PHP注册POST/GET大变量的时候,看到了关于这块的一些东西,跟踪了半天,先记录下来,免得以后再如此麻烦的跟踪.

处理器注册:

  1. [mod_php5.c, mod_php5模块初始化]
  2. php_init_handler(server_rec *s, pool *p)
  3. ->[main/SAPI.c]sapi_startup(&apache_sapi_module)
  4. ->[main/SAPI.c]
  5. sapi_globals_ctor(&sapi_globals)
  6. ->[main/php_content_types.c]php_setup_sapi_content_types(TSRMLS_C)
  7. ->[main/php_content_types.c
  8. php_post_entries如下]sapi_register_post_entries(php_post_entries
  9. TSRMLS_CC)
  10. ->[main/SAPI.c]sapi_register_post_entry(p
  11. TSRMLS_CC)

如下面的代码,共注册了俩个处理器,分别处理post数据和文件上传.

注1:参看在PHP Module中获取$_GET/$_POST/$_COOKIE的方法研究

  1. [main/rfc1867.h]
  2. #define
  3. MULTIPART_CONTENT_TYPE
  4. "multipart/form-data"
  5. [main/php_content_types.h]
  6. #define
  7. DEFAULT_POST_CONTENT_TYPE
  8. "application/x-www-form-urlencoded"
  9. [main/SAPI.c]
  10. struct
  11. _sapi_post_entry
  12. {
  13. char *content_type;
  14. uint
  15. content_type_len;
  16. void
  17. (*post_reader)(TSRMLS_D);
  18. void
  19. (*post_handler)(char *content_type_dup, void *arg
  20. TSRMLS_DC);
  21. };
  22. [main/php_content_types.c]
  23. static
  24. sapi_post_entry
  25. php_post_entries[] = {
  26. {
  27. DEFAULT_POST_CONTENT_TYPE, sizeof(DEFAULT_POST_CONTENT_TYPE)-1, sapi_read_standard_form_data, php_std_post_handler
  28. },
  29. {
  30. MULTIPART_CONTENT_TYPE, sizeof(MULTIPART_CONTENT_TYPE)-1, NULL, rfc1867_post_handler
  31. },
  32. {
  33. NULL, 0, NULL, NULL
  34. }
  35. };
  1. <?php
  2. #*********************************************************
  3. #文件名称: yl_upload.class.php
  4. #功能描述: 印像上传类
  5. #程序制作:留印(adleyliu)
  6. #联系qq :14339095
  7. #联系邮箱:adleyliu@163.com
  8. #最后更新: 2007-11-11
  9. #注:转发时请保留此声明信息,这段声明不并会影响你的速度!
  10. #如有修改请将修改后的文件以邮件形式发送给作者一份,谢谢!
  11. #
  12. #*********************************************************
  13. /*
  14. //使用说明:
  15. //声明一个上传类
  16. $yl_upload = new yl_upload_class();
  17. //设置参数
  18. global $yl_filedata,$yl_directroy,$file_urldirectroy,$yl_settingsnew;
  19. global $yl_maxsize,$yl_sizeformat,$yl_arrext,$yl_ext;
  20. $yl_filedata = 'filedata';//表单名
  21. $yl_directroy = '../upload_file';//上传主目录
  22. $file_urldirectroy = 'upload_file';//文件url(在编辑器KindEditor中用到,请查看upload.php实例)
  23. $yl_settingsnew = 'month_'.date('Ym');//上传主目录1按版块存入不同目录,2按月份存入不同目录,3按天存入不同目录
  24. $yl_maxsize = 2097152; //这里以字节为单位(1024*2)*1024=2097152 = 2M
  25. $yl_sizeformat = 'k'; //显示文件大小单位b,k,m
  26. $yl_arrext = array('gif','jpg','jpeg','png','bmp');//允许上传文件类型
  27. $yl_ext = 0; //0原文件类型上传,1统一为存为jpg
  28. //上传
  29. $yl_upload -> yl_uploadfile();
  30. */
  31. class yl_upload_class
  32. {
  33. #*********************************************************
  34. #创建目录函数
  35. #*********************************************************
  36. function createfolder($yl_path)
  37. {
  38. if (!file_exists($yl_path))
  39. {
  40. $this -> createfolder(dirname($yl_path));
  41. @mkdir($yl_path, 0777);
  42. }
  43. return $this -> createfolder;
  44. }
  45. #*********************************************************
  46. #获取文件名称,大小,类型,临时文件名
  47. #*********************************************************
  48. function yl_getfilename($yl_type)
  49. {
  50. global $yl_filedata,$yl_directroy,$yl_settingsnew;
  51. global $yl_maxsize,$yl_sizeformat,$yl_arrext,$yl_ext;
  52. return $_FILES[$yl_filedata][$yl_type];
  53. }
  54. #*********************************************************
  55. #获取文件大小
  56. #*********************************************************
  57. function yl_getfilesize()
  58. {
  59. global $yl_filedata,$yl_directroy,$yl_settingsnew;
  60. global $yl_maxsize,$yl_sizeformat,$yl_arrext,$yl_ext;
  61. if($this -> yl_getfilename('size') == 0){
  62. $this -> alert("请选择上传文件!");
  63. exit;
  64. }
  65. if($this -> yl_getfilename('size') > $yl_maxsize){
  66. $yl_maxsizek=$yl_maxsize/1024;
  67. $this -> alert("上传文件超出限制范围$yl_maxsizek.K!");
  68. exit;
  69. }
  70. switch (strtolower($yl_sizeformat)){
  71. case 'b':
  72. return $this -> yl_getfilename('size') . ' B';
  73. break;
  74. case 'k':
  75. return ($this -> yl_getfilename('size')/1024) . ' K';
  76. break;
  77. case 'm':
  78. return ($this -> yl_getfilename('size'))/(1024*1024) . ' M';
  79. }
  80. }
  81. #*********************************************************
  82. #获得文件扩展名
  83. #*********************************************************
  84. function yl_getfiletype()
  85. {
  86. global $yl_filedata,$yl_directroy,$yl_settingsnew;
  87. global $yl_maxsize,$yl_sizeformat,$yl_arrext,$yl_ext;
  88. $yl_temp_arr = explode(".", $this -> yl_getfilename('name'));
  89. $yl_file_ext = array_pop($yl_temp_arr);
  90. $yl_file_ext = trim($yl_file_ext);
  91. $yl_file_ext = strtolower($yl_file_ext);
  92. //检查扩展名
  93. if (in_array($yl_file_ext, $yl_arrext) === false) {
  94. $this -> alert("上传文件类型被限制!");
  95. exit;
  96. }
  97. return $yl_file_ext;
  98. }
  99. #*********************************************************
  100. #上传
  101. #*********************************************************
  102. function yl_uploadfile()
  103. {
  104. global $yl_filedata,$yl_directroy,$file_urldirectroy,$yl_settingsnew;
  105. global $yl_maxsize,$yl_sizeformat,$yl_arrext,$yl_ext;
  106. $yl_file_nameold = $this -> yl_getfilename('name');//原文件名
  107. $yl_file_namenews = date('Ymd').'_'.md5(date('YmdHis'));//重命名
  108. if($yl_ext == 0){
  109. $yl_file_names = $yl_file_namenews.'.'.$this -> yl_getfiletype();//改名
  110. }elseif ($yl_ext == 1){
  111. $yl_file_names = $yl_file_namenews.'.jpg';//统一改名为jpg
  112. }
  113. $yl_tmp_name = $this -> yl_getfilename('tmp_name');//服务器上临时文件名
  114. $yl_file_size = $this -> yl_getfilesize();//获取文件大小
  115. $yl_file_type = $this -> yl_getfiletype();//获取文件类型
  116. $yl_file_path = $yl_directroy.'/'.$yl_settingsnew;//建立一个目录
  117. //检查目录是否存在,不存在则创建
  118. if(@is_dir($yl_file_path) === false) {
  119. $this -> createfolder(''.$yl_file_path.'');//创建目录
  120. }
  121. //检查是否已上传
  122. if(@is_uploaded_file($yl_tmp_name) === false) {
  123. $this -> alert("文件已上传!");
  124. exit;
  125. }
  126. //检查目录写权限
  127. if (@is_writable($yl_file_path) === false) {
  128. $this -> alert("上传目录没有写权限!");
  129. exit;
  130. }
  131. $yl_doupload = @copy($yl_tmp_name, ''.$yl_file_path.'/'.$yl_file_names.'');
  132. if($yl_doUpload === false)
  133. {
  134. $this -> alert("上传失败!");
  135. }else{
  136. echo '上传成功';
  137. echo '<br>';
  138. echo '文件目录:'.$yl_file_path.'';
  139. echo '<br>';
  140. echo '原文件名:'.$yl_file_nameold.'';
  141. echo '<br>';
  142. echo '新文件名:'.$yl_file_names.'';
  143. echo '<br>';
  144. echo '文件大小:'.$yl_file_size.'';
  145. echo '<br>';
  146. echo '文件类型:'.$yl_file_type.'';
  147. }
  148. return;
  149. }
  150. #*********************************************************
  151. #*删除文件
  152. #*********************************************************
  153. function delfile()
  154. {
  155. global $yl_filedata,$yl_directroy,$yl_settingsnew;
  156. global $yl_maxsize,$yl_sizeformat,$yl_arrext,$yl_ext;
  157. $yl__dir = dirname(trim($yl_directroy));
  158. if( $this->_isDel( $yl__dir ) )
  159. {
  160. return @unlink( $yl_directroy ) ? true : false;
  161. }else{
  162. return false;
  163. }
  164. }
  165. #*********************************************************
  166. #删除目录 目录下如果有文件不能删除
  167. #*********************************************************
  168. function deldir( )
  169. {
  170. global $yl_filedata,$yl_directroy,$yl_settingsnew;
  171. global $yl_maxsize,$yl_sizeformat,$yl_arrext,$yl_ext;
  172. if( $this->_isdel($yl_directroy) && is_dir( $yl_directroy ) )
  173. {
  174. return @rmdir( $yl_directroy ) ? true : false;
  175. }else{
  176. return false;
  177. }
  178. }
  179. #*********************************************************
  180. #提示
  181. #*********************************************************
  182. function alert($yl_msg)
  183. {
  184. echo '<html>';
  185. echo '<head>';
  186. echo '<title>error</title>';
  187. echo '<meta http-equiv="content-type" c>';
  188. echo '</head>';
  189. echo '<body>';
  190. echo '<script type="text/网页特效">alert("'.$yl_msg.'");;</script>';
  191. echo '</body>';
  192. echo '</html>';
  193. exit;
  194. }
  195. }
  196. ?>