php多文件上传与上传文件原理分析

 更新时间:2016年11月25日 15:51  点击:1223

首先用php教程的socket函数库建立一个临时的http服务器,在某一端口监听,然后把 ip地址和端口号通知客户端,客户端把上传表单提交(临时服务器), 临时服务器接受客户端请求,并读取post数据,分析并获取客户端上传的文件信息,把文件保存在服务器上,然后关闭临时服务器,释放资源,上传完成。有点绕,不过思路还是简单的。

<?php

class upload {
public $up_ext=array(), $up_max=5210, $up_dir;
private $up_name, $up_rename=true, $up_num=0, $up_files=array(), $up_ret=array();

function __construct($name, $ext=array(), $rename=true) {
if (!empty($name)) {
$this->up_name = $name;
!empty($ext) && $this->up_ext = $ext;
$this->up_rename = $rename;
$this->up_dir = website_dirroot.
$globals['cfg_upload_path'];
$this->initupload();
} else {
exit('upload文件域名称为空,初始化失败!');
}
}

private function initupload() {
if (is_array($_files[$this->up_name])) {
$up_arr = count($_files[$this->up_name]);
$up_all = count($_files[$this->up_name], 1);
$up_cnt = ($up_all - $up_arr) / $up_arr;
for ($i = 0; $i < $up_cnt; $i ++) {
if ($_files[$this->up_name]['error'][$i] != 4) {
$this->up_files[] = array(
'tmp_name' => $_files[$this->up_name]['tmp_name'][$i],
'name' => $_files[$this->up_name]['name'][$i],
'type' => $_files[$this->up_name]['type'][$i],
'size' => $_files[$this->up_name]['size'][$i],
'error' => $_files[$this->up_name]['error'][$i]
);
}
}
$this->up_num = count($this->up_files);
} else {
if (isset($_files[$this->up_name])) {
$this->up_files = array(
'tmp_name' => $_files[$this->up_name]['tmp_name'],
'name' => $_files[$this->up_name]['name'],
'type' => $_files[$this->up_name]['type'],
'size' => $_files[$this->up_name]['size'],
'error' => $_files[$this->up_name]['error']
);
$this->up_num = 1;
} else {
exit('没找找到需要upload的文件!');
}
}

$this->chkupload();
}

private function chkupload() {
if (empty($this->up_ext)) {
$up_mime = array('image/wbmp', 'image/bmp', 'image/gif', 'image/pjpeg', 'image/x-png');
foreach ($this->up_files as $up_file) {
$up_allw = false;
foreach ($up_mime as $mime) {
if ($up_file['type'] == $mime) {
$up_allw = true; break;
}
}
!$up_allw && exit('不允许上传'.$up_file['type'].'格式的文件!');

if ($up_file['size'] / 1024 > $this->up_max) {
exit('不允许上传大于 '.$this->up_max.'k 的文件!');
}
}
} else {
foreach ($this->up_files as $up_file) {
$up_ext = end(explode('.', $up_file['name']));

$up_allw = false;
foreach ($this->up_ext as $ext) {
if ($up_ext == $ext) {
$up_allw = true; break;
}
}
!$up_allw && exit('不允许上传.'.$up_ext.'格式的文件!');

if ($up_file['size'] / 1024 > $this->up_max) {
exit('不允许上传大于 '.$this->up_max.'k 的文件!');
}
}
}

$this->uploading();
}

private function uploading() {
if (io::dircreate($this->up_dir)) {
if (chmod($this->up_dir, 0777)) {
if (!empty($this->up_files)) {
foreach ($this->up_files as $up_file) {
if (is_uploaded_file($up_file['tmp_name'])) {
$file_name = $up_file['name'];
if ($this->up_rename) {
$file_ext = end(explode('.', $file_name));
$file_rnd = substr(md5(uniqid()), mt_rand(0, 26), 6);
$file_name = date('ymdhis').'_'.$file_rnd.'.'.$file_ext;
}
$file_name = $this->up_dir.'/'.$file_name;

if (move_uploaded_file($up_file['tmp_name'], $file_name)) {
$this->up_ret[] = str_replace(website_dirroot, '', $file_name);
} else {
exit('文件上传失败!');
}
}
}
}
} else {
exit('未开启写入权限!');
}
} else {
exit('上传目录创建失败!');
}
}

public function getupload() {
return empty($this->up_ret) ? false : $this->up_ret;
}

function __destruct() {}
}
?>


那么上传的流程就是如下了:

1.给form标签的enctype属性赋值multipart/form-date,这个是必须的,而且也必须指定的,不然文件无法上传。

2.判断

这个判断一般有三个判断,一个是类型判断,一个是大小判断,一个是文件是否存在的判断。因为这三个判断是保证安全以及成功上传的前提。

3.保存上传的文件

因为文件上传的时候都被存放在一个临时的地方,所以要通过方法将其转移到指定的地方,这样调用也会很方便。

说了原理和流程,就是实际操作以及一些重要函数了。

首先就是指定文件规定类型,但是不能直接指定,必须指定mime类型,不然php会报错,如果你要了解每个文件后缀对应的mime类型,可以看这儿。

上传的文件的信息一般都包含在一个叫$_files的关联数组中,它包含了五方面的信息。

$_files['file']['name'] =>要上传的文件的原名

$_files['file']['type'] =>要上传的文件的类型

$_files['file']['size'] =>文件的大小

$_files['file']['tmp_name'] =>储存的临时文件名,一般是系统默认

$_files['file']['error'] =>上传相关的错误代码

错误代码可以是一串数字,也可以是一些常量。比如0->upload_err_ok->上传成功。你可以在这儿看到详细的对应。

在转移文件之前,最好使用is_uploaded_file()函数来测试临时文件是否是通过http post上传的,也可以检测文件是否存在,一般用文件的临时名作为参数。让后就是使用move_uploaded_file()函数来转移上传的文件,这个函数有两个参数,第一个是指定要转移的文件,第二个是指定要转移的文件。要转移的文件一般是临时文件,所以用临时文件名(tmp_name)来指定。而第二参数一般也作为新的文件名,存进数据库教程,以后就可以调用了。

这里要说的一个就是大文件上传,在不借助第三方工具的情况下,可以通过设定php.ini的参数来完成,一个是upload_max_filesize,这个是指定上传的最大限制,默认是2m,还有一个就是max_input_time,它指定了表单提交的最长时间限制,因为一般大文件上传比较好时,所以这个也是必须的。

表单还可以有一些其他的控制,比如post_max_size是控制表单能接受的最大值,而memory_list可以指定每个php页面能占有的最大内存,默认是8m,max_input_time可以指定每个php页面接受数据的最长时间,默认是60秒。

 

zend framework invalid command 'rewriteengine'解决办法

zend framework  tutorial时候,运行例子,浏览器报错为:
the server encountered an internal error and was unable to complete your request. either the server is overloaded or there was an error in a cgi script.


apache error.log 中出现如下错误:
invalid command 'rewriteengine', perhaps教程 mis-spelled or defined by a module not included in the server configuration

解决办法:

打开httpd.conf ,取消 loadmodule rewrite_module modules/mod_rewrite.so前的注释

 

.静态变量
在函数内部static $a = 0;
注意:声明中用表达式的结果对其赋值会导致解析错误如static $a =3+3;(error)
静态变量仅在局部函数域中存在(函数内部),函数执行完之后,变量值不会丢失,可用于递归调用

在php教程中的变量范围里,有一个非常重要的变量—php静态变量static。在接下来的这篇文章中,我们将会以具体的代码示例为大家详细介绍有关php静态变量static的主要用法,希望对大家有所帮助。

  看看下面的例子:

  例子 演示需要php静态变量static的例子

  < ?php function test(){ $w3sky = 0; echo $w3sky; $w3sky++; } ?>

  本函数没什么用处,因为每次调用时都会将 $w3sky 的值设为 0 并输出 "0"。将变量加一的 $w3sky++ 没有作用,因为一旦退出本函数则变量 $w3sky 就不存在了。要写一个不会丢失本次计数值的计数函数,要将变量 $w3sky 定义为静态的:

  例子 使用php静态变量static的例子

  < ?php function test(){ static $w3sky = 0; echo $w3sky; $w3sky++; } ?>

  现在,每次调用 test() 函数都会输出 $w3sky 的值并加一。

  静态变量也提供了一种处理递归函数的方法。递归函数是一种调用自己的函数。写递归函数时要小心,因为可能会无穷递归下去。必须确保有充分的方法来中止递归。一下这个简单的函数递归计数到 10,使用静态变量 $count 来判断何时停止

 

<?php
function zdy ()
{
     static $message = 0;       //初始化一个静态变量
     $message+=1;               //静态变量加1
     echo $message." ";         //输出静态变量 
     }
function zdy1()               
{
     $message = 0;    //声明函数内部变量
   $message += 1;    //局部变量加1
     echo $message." ";   //输出局部变量
     }
for($i=0;$i<10;$i++)            //输出1到10
  zdy();
echo "<p>";
for($i=0;$i<10;$i++)   //输出10个1
  zdy1();
echo "<br>";
?>

输出的是:
1 2 3 4 5 6 7 8 9 10
1 1 1 1 1 1 1 1 1 1

 

全局变量
在函数体内定义的global变量,函数体外可以使用,在函数体外定义的global变量不能在函数体内使用,在全局范围内访问变量可以用特殊的 php 自定义 $globals 数组:
如:$globals["b"] = $globals["a"] + $globals["b"];
在一个函数域内用 global 语句导入的一个真正的全局变量实际上是建立了一个到全局变量的引用
global $obj;
注:对于变量的 static 和 global 定义是以 应用 的方式实现的

 

6.给变量赋值:传地址赋值(简单引用):
$bar = &$foo; //加&符号到将要赋值的变量前
改动新的变量将影响到原始变量,这种赋值操作更加快速
注意:只有命名变量才可以传地址赋值
注意:如果
$bar = &$a;
$bar = &$foo;
改变$bar的值只能改变变量foo的值,而不改变a的值(引用改变了)

 

<?php

$my_var = 'hello world';

test_global();

function test_global() {

    // now in local scope
   
    // the $my_var variable doesn't exist
   
    // produces error: "undefined variable: my_var"
   
    echo $my_var;
   
    // now let's important the variable
   
    global $my_var;
   
    // works:
   
    echo $my_var;
   
}

?>

//如何提取远程图片url地址中的相对地址,并创建文件夹

$imgurl = "http://www.111cn.net /images/l/201011/sjfzgm1289209745159.jpg" ;

//去掉"http:/"
$imgurl2 = substr($imgurl,6);

$imgurl3 = strstr($imgurl2,'/');                              //这就变成了:$imgurl3 == "/images/l/201011/sjfzgm1289209745159.jpg ";

//接下来翻转字符串
$imgurl4 = strrev($imgurl3);                                 //这就变成了:$imgurl4 == "/gpj.9515479029821mgzfjs/110102/l/segami/";
//去掉"/"
$imgurl4 = substr($imgurl3,1);                             //这就变成了:$imgurl4 == "gpj.9515479029821mgzfjs/110102/l/segami/";

//去掉文件名
$imgurl5 = strstr($imgurl4,'/');                             //这就变成了:$imgurl4 == "/110102/l/segami/";

//再翻转,还原
$imgurl6 = strrev($imgurl5);                                //这就变成了:$imgurl6 == "/images/l/201011/";

/*
通常是 <img src="                                        ">这样匹配的
也有 url("")

接着获得相对地址  ,先判断 域名  这个去找

../
./
/
这么三种是目录的表现
图片的扩展名就那么几个

应该写出来就能用的吧

*/
//用正则提取标签里的内容


$str = '<p>文字</p>
<span>文字2
</span>';

$preg = '/<.+?>(.+?)</.+?>/is';

preg_match_all($preg, $str, $result);

print_r($result[1]);

php教程 多文件上传的处理方法

关于多文件上传我们讲过很多了,下面是一个简单的普通form多文件上传类了,需要的朋友可以下载试用一下。
<?php
  
       class upload {
             public $up_ext=array(), $up_max=5210, $up_dir;
             private $up_name, $up_rename=true, $up_num=0, $up_files=array(), $up_ret=array();

             function __construct($name, $ext=array(), $rename=true) {
                 if (!empty($name)) {
                     $this->up_name = $name;
                     !empty($ext) && $this->up_ext = $ext;
                     $this->up_rename = $rename;
                     $this->up_dir = website_dirroot.
                                     $globals['cfg_upload_path'];                
                     $this->initupload();
                 } else {
                     exit('upload文件域名称为空,初始化失败!');
                 }
             }

             private function initupload() {
                 if (is_array($_files[$this->up_name])) {
                     $up_arr = count($_files[$this->up_name]);
                     $up_all = count($_files[$this->up_name], 1);
                     $up_cnt = ($up_all - $up_arr) / $up_arr;
                     for ($i = 0; $i < $up_cnt; $i ++) {
                          if ($_files[$this->up_name]['error'][$i] != 4) {
                              $this->up_files[] = array(
                                  'tmp_name' => $_files[$this->up_name]['tmp_name'][$i],
                                  'name' => $_files[$this->up_name]['name'][$i],
                                  'type' => $_files[$this->up_name]['type'][$i],
                                  'size' => $_files[$this->up_name]['size'][$i],
                                  'error' => $_files[$this->up_name]['error'][$i]
                              );
                          }
                     }
                     $this->up_num = count($this->up_files);
                 } else {
                     if (isset($_files[$this->up_name])) {
                         $this->up_files = array(
                              'tmp_name' => $_files[$this->up_name]['tmp_name'],
                              'name' => $_files[$this->up_name]['name'],
                              'type' => $_files[$this->up_name]['type'],
                              'size' => $_files[$this->up_name]['size'],
                              'error' => $_files[$this->up_name]['error']
                         );
                         $this->up_num = 1;
                     } else {
                         exit('没找找到需要upload的文件!');
                     }
                 }
 
                 $this->chkupload();
             }

             private function chkupload() {
                 if (empty($this->up_ext)) {
                     $up_mime = array('image/wbmp', 'image/bmp', 'image/gif', 'image/pjpeg', 'image/x-png');
                     foreach ($this->up_files as $up_file) {
                         $up_allw = false;
                         foreach ($up_mime as $mime) {
                             if ($up_file['type'] == $mime) {
                                 $up_allw = true; break;
                             }
                         }
                         !$up_allw && exit('不允许上传'.$up_file['type'].'格式的文件!');

                         if ($up_file['size'] / 1024 > $this->up_max) {
                             exit('不允许上传大于 '.$this->up_max.'k 的文件!');
                         }
                     }
                 } else {
                     foreach ($this->up_files as $up_file) {
                         $up_ext = end(explode('.', $up_file['name']));

                         $up_allw = false;
                         foreach ($this->up_ext as $ext) {                            
                             if ($up_ext == $ext) {
                                 $up_allw = true; break;
                             }
                         }
                         !$up_allw && exit('不允许上传.'.$up_ext.'格式的文件!');

                         if ($up_file['size'] / 1024 > $this->up_max) {
                             exit('不允许上传大于 '.$this->up_max.'k 的文件!');
                         }
                     }
                 }

                 $this->uploading();
             }

             private function uploading() {
                 if (io::dircreate($this->up_dir)) {
                     if (chmod($this->up_dir, 0777)) {
                         if (!empty($this->up_files)) {
                             foreach ($this->up_files as $up_file) {
                                 if (is_uploaded_file($up_file['tmp_name'])) {
                                     $file_name = $up_file['name'];
                                     if ($this->up_rename) {
                                         $file_ext = end(explode('.', $file_name));
                                         $file_rnd = substr(md5(uniqid()), mt_rand(0, 26), 6);
                                         $file_name = date('ymdhis').'_'.$file_rnd.'.'.$file_ext;
                                     }
                                     $file_name = $this->up_dir.'/'.$file_name;

                                     if (move_uploaded_file($up_file['tmp_name'], $file_name)) {
                                         $this->up_ret[] = str_replace(website_dirroot, '', $file_name);
                                     } else {
                                         exit('文件上传失败!');
                                     }
                                 }
                             }
                         }
                     } else {
                         exit('未开启写入权限!');
                     }
                 } else {
                     exit('上传目录创建失败!');
                 }
             }

             public function getupload() {
                 return empty($this->up_ret) ? false : $this->up_ret;
             }

             function __destruct() {}
       }
?>

于大量文件或大体积文件的情况可以考虑调用组件解决(如前文提到的swfupload组件)。然而有些情况只需要传递几个文件,而且文件体积并不太大,这种情况下使用组件则有点牛刀杀鸡的感觉,通过html自带的<input type="file">表单就可以实现需要的功能,关键在于后台接收程序的处理。

    php处理上传做的很方便,上传文件的信息通过服务器自动处理到$_files数组中,开发者只需要使用的内置处理函数简单操作就可以啦。asp教程开发者则没有这么幸运,官方并没有提供直接的处理方法,需要开发者自己设计,这时就需要开发者了解iis对enctype="multipart/form-data"表单的处理方式,iis把enctype="multipart/form-data"表单提交的数据存储成二进制数据,以二进制格式返回给开发者,开发者则需要通过lenb、midb的字节处理函数来分析获取的上传内容,客户端发送的具体表单数据格式,可以了解下http rfc1867协议传输格式方面的知识。

[!--infotagslink--]

相关文章

  • php无刷新利用iframe实现页面无刷新上传文件(1/2)

    利用form表单的target属性和iframe 一、上传文件的一个php教程方法。 该方法接受一个$file参数,该参数为从客户端获取的$_files变量,返回重新命名后的文件名,如果上传失...2016-11-25
  • Php文件上传类class.upload.php用法示例

    本文章来人大家介绍一个php文件上传类的使用方法,期望此实例对各位php入门者会有不小帮助哦。 简介 Class.upload.php是用于管理上传文件的php文件上传类, 它可以帮...2016-11-25
  • PHP文件上传一些小收获

    又码了一个周末的代码,这次在做一些关于文件上传的东西。(PHP UPLOAD)小有收获项目是一个BT种子列表,用户有权限上传自己的种子,然后配合BT TRACK服务器把种子的信息写出来...2016-11-25
  • jQuery实现简单的文件上传进度条效果

    本文实例讲述了jQuery实现文件上传进度条效果的代码。分享给大家供大家参考。具体如下: 运行效果截图如下:具体代码如下:<!DOCTYPE html><html><head><meta charset="utf-8"><title>upload</title><link rel="stylesheet...2015-11-24
  • php文件上传你必须知道的几点

    本篇文章主要说明的是与php文件上传的相关配置的知识点。PHP文件上传功能配置主要涉及php.ini配置文件中的upload_tmp_dir、upload_max_filesize、post_max_size等选项,下面一一说明。打开php.ini配置文件找到File Upl...2015-10-21
  • PHP判断上传文件类型的解决办法

    分享给大家php判断上传文件类型的方法,大家一起学习学习。/** * 读取文件前几个字节 判断文件类型 * @return String */ function checkTitle($filename){ $file=fopen($filename, "rb"); $bin=fread($file, 2); /...2015-10-21
  • 借助FileReader实现将文件编码为Base64后通过AJAX上传

    这篇文章主要介绍了借助FileReader实现将文件编码为Base64后通过AJAX上传的方法,包括后端对文件数据解码并保存的PHP代码,需要的朋友可以参考下...2015-12-25
  • js实现上传文件添加和删除文件选择框

    这篇文章主要为大家详细介绍了js实现上传文件添加和删除文件选择框 ,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2016-10-25
  • jQuery+ajax简单实现文件上传的方法

    这篇文章主要介绍了jQuery+ajax简单实现文件上传的方法,结合实例形式简单分析了jQuery基于ajax的post方法进行文件传输及asp.net后台处理技巧,需要的朋友可以参考下...2016-06-12
  • Vue使用formData格式类型上传文件的示例

    这篇文章主要介绍了Vue使用formData格式类型上传文件的示例代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-09-04
  • 适用于初学者的简易PHP文件上传类

    本文实例讲述了PHP多文件上传类,分享给大家供大家参考。具体如下:<&#63;phpclass Test_Upload{ protected $_uploaded = array(); protected $_destination; protected $_max = 1024000; protected $_messages =...2015-10-30
  • js 实现文件上传样式详情

    这篇文章主要介绍了js 实现文件上传样式,下面文章举例说明js 是如何实现文件上传样式的,附有代码详细解说,需要的朋友可以参考一下,希望对你有所帮助...2021-10-21
  • PHP利用APC模块实现大文件上传进度条的方法

    php 大文件带进度的上传,一直是一个令php程序员很苦恼的问题。查询baidu 、Google ,大体做带进度的上传方式为:flash+php,socket,apc+php等,下面我介绍了apc +php+ajax制作的带进度的上传,并贴出源码,希望对大家有用。 Altern...2015-10-30
  • C#文件上传的简单实现

    这篇文章主要为大家详细介绍了C#文件上传的简单实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • TypeScript前端上传文件到MinIO示例详解

    这篇文章主要为大家介绍了TypeScript前端上传文件到MinIO示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪...2022-10-12
  • c# FTP上传文件实例代码(简易版)

    下面小编就为大家分享一篇c# FTP上传文件的实例代码,超简单哦~希望对大家有所帮助。一起跟随小编过来看看吧,...2020-06-25
  • php需登录的文件上传管理系统

    本文给大家介绍一个不错的需要登录的php 文件上传管理系统,功能简单有需要了解的同学可参考。 代码如下<&#63;php$admin_pw="admin";//管理密码$uploaddir="upload";//上传目录session_start();if($_GET['action']=="g...2015-10-30
  • asp.net html控件的File控件实现多文件上传实例分享

    asp.net中html控件的File控件实现多文件上传简单实例,开发工具vs2010使用c#语言,感兴趣的朋友可以了解下,必定是多文件上传值得学习,或许本文所提供的知识点对你有所帮助...2021-09-22
  • JQuery异步提交表单与文件上传功能示例

    这篇文章主要介绍了JQuery异步提交表单与文件上传功能,结合实例形式分析了jQuery表单提交及文件传输操作的相关实现技巧,需要的朋友可以参考下...2017-01-16
  • PHP文件上传主要代码讲解

    复制代码 代码如下:<?php if($_FILES['myfile']['name'] != '') { if($_FILES['myfile']['error'] > 0) { echo "错误状态:" . $_FILES['myfile']['error']; } else { move_uploaded_f...2013-10-04