‘壹’ php文件上传,提示移动文件失败
php文件上传,提示移动文件失败,基本是上传保存的目录不可写造成的,需要好好设置一下,下面是一个PHP文件上传的简单例子,仅作参考:
<formaction=""enctype="multipart/form-data"method="post"
name="uploadfile">上传文件:<inputtype="file"name="upfile"/><br>
<inputtype="submit"value="上传"/></form>
<?php
//print_r($_FILES["upfile"]);
if(is_uploaded_file($_FILES['upfile']['tmp_name'])){
$upfile=$_FILES["upfile"];
//获取数组里面的值
$name=$upfile["name"];//上传文件的文件名
$type=$upfile["type"];//上传文件的类型
$size=$upfile["size"];//上传文件的扰塌基大小
$tmp_name=$upfile["tmp_name"];//上传文件的临时存放路径
//判断是否为图片
switch($type){
case'image/pjpeg':$okType=true;
break;
case'image/jpeg':$okType=true;
break;
case'image/gif':$okType=true;
break;
case'image/png':$okType=true;
break;
}
if($okType){
/**
*0:文件上传成功<br/>
*1:超过了文件大小,在php.ini文件中设置<br/>
*2:超过了文件的大小MAX_FILE_SIZE选项指定的值<br/>
*3:文件只有部分被上传<br/>
*4:没有文件被上传<br/>
*5:上传文件大小为0
*/
$error=$upfile["error"];//上传后系统返回的值
echo"================<br/>";
echo"上传文件名称是:".$name."<br/>";
echo"上传文件类型是:".$type."<br/>";
echo"上传文件大小是:".$size."<br/>";
echo"上传后系统返回的值是:".$error."<br/>";
echo"上传文件的临时存放路径是:".$tmp_name."<br/>";
echo缓谨"开始移动上传文件<br/>";
//把上传的临时文件移动到up目录下面
move_uploaded_file($tmp_name,'up/'.$name);
$destination="up/".$name;
echo"================<br/>";
echo"上传信息:<br/>";
if($error==0){
echo"文件上传成功啦!";
echo"<br>图片预览:<br>";
echo"<imgsrc=".$destination.">";
//echo"alt="图片预览: 文件名:".$destination." 上传时间:">";
}elseif($error==1){
echo"超衫余过了文件大小,在php.ini文件中设置";
}elseif($error==2){
echo"超过了文件的大小MAX_FILE_SIZE选项指定的值";
}elseif($error==3){
echo"文件只有部分被上传";
}elseif($error==4){
echo"没有文件被上传";
}else{
echo"上传文件大小为0";
}
}else{
echo"请上传jpg,gif,png等格式的图片!";
}
}
?>
‘贰’ php 图片上传move_uploaded_file 出错
上传文件不存在。很可能是PHP临时文件夹不存在导致的。
<?php
/*
* 文件上传类
*/
class Uploads{
//上传文件
private $uploadFile;
//上传文件扩展名
private $ext = array('jpeg','jpg','gif','png');
//上传文件大小
private $size = 5000000;
//上传文件目录
private $uploadDir = './uploads/';
//是否自定义名称,默认FALSE
private $newName = '';
//上传文件是否可读,默认为TRUE
private $isRead = TRUE;
//上传文件是否可写,默认为TRUE
private $isWrite = TRUE;
//上传信息
private $info;
/*
* 文件上传类初始化
*/
public function __construct($newName='',$ext='',$size='',$dir='',$isRead=TRUE,$isWrite=TRUE){
$this->ext = empty($ext)?$this->ext:$ext;
$this->size = empty($size)?$this->size:$size;
$this->dir = empty($dir)?$this->uploadDir:$dir;
$this->newName = $newName;
$this->isRead = $isRead?TRUE:FALSE;
$this->isWrite = $isWrite?TRUE:FALSE;
}
/*
* 处理上传文件
*/
public function doUpload(){
$this->checkData();
$this->checkFile() or $this->error();
$this->checkExt() or $this->error();
$this->checkSize() or $this->error();
$this->checkError() or $this->error();
$this->checkDir() or $this->error();
$this->upload() or $this->error();
return $this->info['msg'];
}
/*
* 处理上传文件数据
*/
public function checkData(){
$num = 0;
$newArr = array();
foreach($_FILES as $v){
if(is_array($v['name'])){
$count = count($v['name']);
for($i=0; $i<$count; $i++){
foreach($v as $m=>$n){
$newArr[$num][$m] = $n[$i];
}
$num++;
}
}else{
$newArr[$num] = $v;
$num++;
}
}
$endArr = array();
foreach($newArr as $v){
if($v['name'] != ''){
$endArr[]=$v;
}
}
$this->uploadFile = $endArr;
}
/*
* 检测上传文件是否存在
*/
private function checkFile(){
if(empty($this->uploadFile)){
$this->info['error'] = '上传文件不得为空!!!';
return FALSE;
}
return TRUE;
}
/*
* 检测上传文件类型是否合法
*/
private function checkExt(){
if(!is_array($this->ext)){
$this->ext = explode(',', $this->ext);
}
foreach($this->uploadFile as $v){
$ext = strtolower(substr(strrchr(basename($v['name']),'.'),1));
if(!in_array($ext,$this->ext)){
$this->info['error'] = '上传文件类型非法,禁止上传!!!';
return FALSE;
}
}
return TRUE;
}
/*
* 检测上传文件大小
*/
private function checkSize(){
foreach($this->uploadFile as $v){
if($v['size']>$this->size){
$this->info['error'] = '上传文件体积过大,上传失败!!!';
return FALSE;
}
}
return TRUE;
}
/*
* 检测文件上传错误代码
*/
private function checkError(){
foreach($this->uploadFile as $v){
switch($v['error']){
case 0:
return TRUE;
break;
case 1:
$this->info['error'] = '上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值,上传失败!!!';
return FALSE;
break;
case 2:
$this->info['error'] = '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值,上传失败!!!';
return FALSE;
break;
case 3:
$this->info['error'] = '文件只有部分被上传!!!';
return FALSE;
break;
case 4:
$this->info['error'] = '没有文件上传!!!';
return FALSE;
break;
}
}
return TRUE;
}
/*
* 检测上传文件夹是否存在
*/
private function checkDir(){
if(!file_exists($this->uploadDir)){
mkdir($this->uploadDir,0777,true);
}
if(!is_writeable($this->uploadDir)){
$this->info['error'] = '上传目录没有写入权限,上传失败!!!';
return FALSE;
}
return TRUE;
}
/*
* 上传文件
*/
private function upload(){
date_default_timezone_set('PRC');
//检测文件是否自定义名称
$name = empty($this->newName)?date('Ymd_His'):$this->newName;
foreach($this->uploadFile as $k=>$v){
$upload_path = $this->uploadDir.$name.'_'.($k+1).strrchr(basename($v['name']),'.');
$upload_path = iconv('UTF-8','gbk',$upload_path);
if(is_uploaded_file($v['tmp_name'])){
if(move_uploaded_file($v['tmp_name'], $upload_path)){
if($this->isRead && $this->isWrite){
chmod($upload_path,0777);
}else if($this->isRead && !$this->isWrite){
chmod($upload_path,0444);
}else if(!$this->isRead && $this->isWrite){
chmod($upload_path,0222);
}else{
chmod($upload_path,0000);
}
$this->info['msg']=array('type'=>1,'success'=>'文件上传成功','path'=>iconv('gbk','UTF-8',$upload_path));
}else{
$this->info['error'] = '文件上传失败!!!';
return FALSE;
}
}
}
return TRUE;
}
/*
* 上传成功的方法
*/
public function success(){
echo $this->info['msg']['success'];
}
/*
* 上传文件错误方法
*/
public function error(){
echo $this->info['error'];
die;
}
这是我写的PHP类,你可以参考一下。有什么特殊需要的,你可以告诉我一下,完善一下上传类。
‘叁’ php文件上传失败的问题
在用PHP进行文件上传的操作中,需要知道怎么控制上传文件大小的设置,而文件可传大小是受到多种因素制约的,现总结如下:
1、php.ini:upload_max_filesize 所上传的文件的最大大小。默认值2M。
2、php.ini:memory_limit 本指令设定了一个脚本所能够申请到的最大内存字节数,默认值8M。如果不需要任何内存上的限制,必须将其设为 -1。如果内存不够,则可能出现错误:Fatal error: Allowed memory size of X bytes exhausted (tried to allocate Y bytes)
3、php.ini:post_max_size 设定POST数据所允许的最大大小。此设定也影响到文件上传。要上传大文件,该值必须大于 upload_max_filesize。
4、php.ini:max_execution_time = 30 ; Maximum execution time of each script, in seconds
5、php.ini:max_input_time = 60 ; Maximum amount of time each script may spend parsing request data
6、如果用到mysql的BLOB进行二进制文件存储,则需要设置my.ini:max_allowed_packet=xxM
7、httpd.conf
在 Apache 里面有一个选项是 LimitRequestBody,这个选项可以限制用户送出的 HTTP 请求内容。这个选项可以在 .htaccess 或 httpd.conf 里使用,而如果在 httpd.conf 内使用,分别可以用在 virtualhost 或目录属性设定。而 LimitRequestBody 的设定值是介乎 0 (无限制) 至 2147483647 (2GB)。
例如要在目录 D:/AppServ/www 设定上传限制为 100K,可以在 .htaccess 或 httpd.conf 加入以下语句:
LimitRequestBody 1024000000
Options Indexes FollowSymLinks MultiViews ExecCGI
AllowOverride All
Order allow,deny
Allow from all
LimitRequestBody 1024000000Options Indexes FollowSymLinks MultiViews ExecCGIAllowOverride AllOrder allow,denyAllow from all
如果透过 .htaccess 设定,储存档案后会立即生效;如透过 httpd.conf 设定,须要重新启动 Apache。
PHP关于文件上传部分,特别提到表单隐藏域:MAX_FILE_SIZE,意思是接收文件的最大尺寸。文档中给出的例子如下:
<form enctype=”multipart/form-data” action=”_URL_” method=”POST”>
<input type=”hidden” name=”MAX_FILE_SIZE” value=”30000″>
Send this file: <input name=”userfile” type=”file”>
<input type=”submit” value=”Send File”>
form>
Send this file:
这里设置MAX_FILE_SIZE = 30000,期待一种可能,使得浏览器在传送文件之前能够依此作出预先判断,如果文件尺寸大于30000字节,则不执行实际的POST动作。也就是不往服务器发送文件内容,而是直接在客户端提醒用户“你试图上传的文件超过30000字节”。
这的确是一个非常棒的主张,但在现实中却暂时无法实现。不是因为这个限制可以“被简单地绕过”,而是IE和FireFox这两个主流浏览器都不支持这个特性。PHP的这个建议尚未被采纳。
MAX_FILE_SIZE还有一个用场:后台PHP会判断接收到的文件大小是否大于这个值,如果超出,$_FILES[‘thisfile’][‘error’]会被设置为UPLOAD_ERR_FORM_SIZE(2),同时放弃保存临时文件,将$_FILES[‘thisfile’][‘size’]置0。
这个例子,没问题,表现正常,当我试图上传一个40多K的文件时,PHP程序报告“文件超过MAX_FILE_SIZE”。
但是,如果我们将表单中的MAX_FILE_SIZE从30000减少到1000,情形又如何呢?
上传800字节的文件,正常;
上传40K的文件,PHP报告文件过大,也正常;
上传3000个字节的文件,PHP未报告错误,它成功保存了文件!出乎意料!
问题就出在main/rfc1867.c中判断文件是否超长的这部分代码上。php每次从buffer中读取FILLUNIT字节长度的内容后,首先判断“已经读到的内容长度(total_bytes)”是否大于MAX_FILE_SIZE,然后再增加“已经读到的内容长度(total_bytes)”。这样一来,和预计的结果之间至多会有FILLUNIT字节的误差,而FILLUNIT=1024*5=5K。(点击bug了解详细内容)
这就是说,当MAX_FILE_SIZE<5K时,上传一个大于MAX_FILE_SIZE,但是小于5K的文件是没有问题的。
当然,因为这个设置很容易被绕过,所以服务器端编程不应当依赖于MAX_FILE_SIZE。而且,5K到底是个很小的数值,对大多数上传文件的表单来说没有影响。
PHP中post_max_size,upload_max_filesize, MAX_FILE_SIZE的设置,和客户端上传给服务器端的流量大小无关。
Apache服务器从客户端接收长度不超过LimitRequestBody字节数的请求,然后传送给php模块,php模块再决定是否保存成临时文件,设置$_FILES全局变量,移交给script进一步处理。
这个Apache的LimitRequestBody选项缺省值=0,允许Request body的最大字节数是2G(Linux + Apache)
最后还要注意的是:
html本身能够post数据也是有限制的,不能超过2G。
FTP客户端有文件偏移指针的2GB边界限制,未使用特殊编译flag编译的ftp服务器端或者客户端,无论在什么FS中都不支持大于2GB的文件。不知道PHP会不会也有这种情况。
‘肆’ php上传问题 在上传不成功的情况下,当上传文件大于10M(大概数)时就会报错,而不是根据程序提示,
你说的10M应该是php.ini里设置的上传文件大小限制,而你这个switch判断是基于表单上传文件大小来判断的,两者毫无相关!
一、超过10M,在php底层处理请求时就直接报错了,根本执行不到你switch的地方,所以报错是非预期的
二、超过2M,php能正常执行,所以会按照你switch来报错
这里,你要搞清楚php的上传文件大小限制跟form表单上传文件大小限制的关系
‘伍’ PHP上传文件失败
提示显示的很清楚的。文件已经上传了行洞,但是在把文件薯吵从临时文档手枯件夹移出来出错了。注意新地址是否正确
可以使用绝对路径或者相对路径,看个人http://www.hi-docs.com/php/move_uploaded_file.html
‘陆’ 瑙e喅nginx+php-fpm镞犳硶涓娄紶鏂囦欢闂棰
瑙e喅锷炴硶
location ~ .php$ {
root /var/www/html/public;
client_max_body_size 50M;
client_body_temp_path /tmp;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
闄勶细涓嶈佹垒浜嗭纴缃戜笂璇寸殑寰埚氭垜閮借瘯杩!涓鐩存彁绀篎irebug 杈惧埌浜 Post 璇锋眰澶у皬闄愬埗
淇鏀笔HP.ini涓璸ost_max_size upload_max_filesize max_execution_time max_input_time
镓揿紑php.ini鏂囦欢锛屼慨鏀瑰畬姣曞悗閲嶅惎链嶅姟鍣ㄣ傛祴璇曚笅涓娄紶鏂囦欢銆伞伞伞(鍢诲樆锛屾槸涓嶆槸浼犱笂浜嗗緢澶х殑鏂囦欢?)
1銆佹枃浠朵笂浼犳椂瀛樻斁鏂囦欢镄勪复镞剁洰褰曘傚繀椤绘槸 PHP 杩涚▼镓链夎呯敤鎴峰彲鍐欑殑鐩褰曘傚傛灉链鎸囧畾鍒 PHP 浣跨敤绯荤粺榛樿ゅ紁hp.ini鏂囦欢涓璾pload_tmp_dir鐢ㄦ潵璇存槑PHP涓娄紶镄勬枃浠舵斁缃镄勪复镞剁洰褰曘
瑕佹兂涓娄紶鏂囦欢锛屽缑淇濊瘉链嶅姟鍣ㄦ病链夊叧闂涓存椂鏂囦欢鍜屾湁瀵规枃浠跺す镄勫啓𨱒冮檺
2銆乵ax_execution_time
鍙橀噺max_execution_time璁剧疆浜嗗湪寮哄埗缁堟㈣剼链鍓峆HP绛夊緟鑴氭湰镓ц屽畬姣旷殑镞堕棿锛屾ゆ椂闂翠互绉掕$畻銆傚綋鑴氭湰杩涘叆浜嗕竴涓镞犻檺寰鐜鐘舵 镞舵ゅ彉閲忛潪甯告湁鐢ㄣ傜劧钥岋纴褰揿瓨鍦ㄤ竴涓闇瑕佸緢闀挎椂闂村畬鎴愮殑钖堟硶娲诲姩镞(渚嫔备笂浼犲ぇ鍨嬫枃浠)锛岃繖椤瑰姛鑳戒篃浼氩艰嚧镎崭綔澶辫触銆傚湪杩欐牱镄勬儏鍐典笅蹇呴’钥冭槛灏嗘ゅ彉閲忓煎 锷狅纴浠ラ伩鍏峆HP鍦ㄨ剼链姝e湪镓ц屾煇浜涢吨瑕佽繃绋嬬殑镞跺椤皢鑴氭湰鍏抽棴銆
淇鏀逛负锛歮ax_execution_time =800
3銆乫ile_uploads = On(铡熸潵闂寮灏变笉鐢ㄨ剧疆浜)
4銆乽pload_max_filesize =2M淇鏀逛负800M
5銆佸悓琛ㄥ崟鎻愪氦鐩稿叧镄勪竴涓鍙橀噺鏄痯ost_max_size锛屽畠灏嗘带鍒跺湪閲囩敤POST鏂规硶杩涜屼竴娆¤〃鍗曟彁浜や腑PHP镓鑳藉熸帴鏀剁殑链澶ф暟鎹閲忋备技涔庝笉澶 鍙鑳介渶瑕佸皢榛樿ょ殑8 MB鏀瑰缑镟村ぇ銆傜浉鍙嶏纴搴斿綋阃傚綋灏嗗叾闄嶅埌镟翠负瀹为檯镄勬暟鍊笺备絾濡傛灉甯屾湜浣跨敤PHP鏂囦欢涓娄紶锷熻兘锛屽垯闇瑕佸皢姝ゅ兼敼涓烘瘆upload_max_filesize杩 瑕佸ぇ銆
涔熶慨鏀逛负锛歱ost_max_size =900M
6銆乵ax_input_time
姝ゅ彉閲忓彲浠ヤ互绉掍负鍗曚綅瀵归氲繃POST銆丢ET浠ュ强PUT鏂瑰纺鎺ユ敹鏁版嵁镞堕棿杩涜岄檺鍒躲傚傛灉搴旂敤绋嫔簭镓杩愯岀幆澧冨勫湪浣庨熼摼璺涓婏纴鍒欓渶瑕佸炲姞姝ゅ间互阃傚簲鎺ユ敹鏁版嵁镓闇镄勬洿澶氭椂闂.
淇鏀逛负锛歮ax_input_time =900
7銆乵emory_limit =10M
涓轰简阆垮厤姝e湪杩愯岀殑鑴氭湰澶ч噺浣跨敤绯荤粺鍙鐢ㄥ唴瀛桡纴PHP鍏佽稿畾涔夊唴瀛树娇鐢ㄩ檺棰濄傞氲繃memory_limit鍙橀噺𨱒ユ寚瀹氩崟涓鑴氭湰绋嫔簭鍙浠ヤ娇鐢ㄧ殑链澶у唴瀛桦归噺
鍙橀噺memory_limit镄勫(涓嶈佽秴鍑烘湇锷″櫒鍐呭告渶澶у)
淇鏀逛负锛歮emory_limit =128M
‘柒’ php无法上传文件
我也遇到过,我是APACHE+PHP的环境。
造成这个情况的原因可能比较多,我也只说的出来几个,你试一下
1.PHP程序的问题,如果可能的话,看一下源代码的上传模块。
2.上传文件的文件名必须是中文,或者必须是英文or数字.
3.如果有后台的话,则有可能是后台的功能配置,特别注意一下上传文件的大小与格式。
如果还是不能上传,我就怀疑是上传模块的问题了,你可以给你的Php站加一个上传模块,或者从后台上传。
而且有的模块是只能从后台上传,也就是只有管理员可以上传。
‘捌’ php 图片上传有个小BUG,求大神解答。以下是我的一些代码
您好,这个是 PHP 的一个 BUG(毕竟是外国人做的,中文支持不太好)。
PHP 中,上传中文文件基本上都会出错,所以只要在移动文件时,将文件重命名就可以了。
(如果需要原文件名,只需要将原文件名和重命名后的文件名保存在数据库中就可以了)
代码如下(您的代码有一些漏洞与不规范之处,这里已更正):
//检测文件MIME类型,如果不是图片则阻止本次上传
//不要相信$_FILES['file']['type'],这是可以伪造的
//如果PHP>=5.3.0,则使用finfo函数来获取文件类型
//因为PHP>=5.3.0放弃了mime_content_type()函数
if(version_compare(PHP_VERSION,'5.3.0','>=')){
$f=finfo(FILEINFO_MIME_TYPE);
$ftype=explode('/',finfo_file($f,$_FILES['file']['tmp_name']));
finfo_close($f);
$f=NULL;
if($ftype[0]!=='image'){
@unlink($_FILES['file']['tmp_file']);
die('文件上传失败!<br/>请重新上传。<br/><ahref="pfabu.html">返回</a>');
}
$ftype=NULL;
}
else{
$ftype=explode('/',mime_content_type($_FILES['file']));
if($ftype[0]!=='image'){
@unlink($_FILES['file']['tmp_file']);
die('文件上传失败!<br/>请重新上传。<br/><ahref="pfabu.html">返回</a>');
}
$ftype=NULL;
}
$link=mysql_connect('localhost','root','123456');
mysql_query('setnames'UTF8'');
mysql_select_db('zhenyu',$link);
//为了防止SQL注入,对数据进行转义
$pkind=addslashes($_POST['pkind']);
$pname=addslashes($_POST['pname']);
$pshow=addslashes($_POST['pshow']);
$filename_upload=$_FILES['file']['name'];
//Base64编码后的字符只含有a-zA-Z0-9以及+,/,=
$filename=base64_encode($filename_upload);
//Base64编码中有一些非文件名可用的字符,把它们替换掉
$filename=strtr($filename,array(
'+'=>'.',
'/'=>'_',
'='=>'-'
)
);
//上传后的文件保存在proct文件夹
$file_move='proct/'.$filename;
//如果文件已存在,则在文件名后加上-和一个随机数
//当然,这一部分也可以您自己更改,不会影响结果
if(file_exists($file_move)){
$rand='-'.strval(rand(0,9999));
$file_move.=$rand;
$filename_upload.=$rand;
//因为$rand被其它变量引用,不能直接注销
//所以将其赋值为NULL,也可达到同样的释放内存的效果
$rand=NULL;
}
//判断文件是否是通过HTTPPOST上传的
//这可以用来确保恶意用户无法欺骗程序去访问本不该访问的文件,例如/etc/passwd
if(!is_uploaded($_FILES['file']['tmp_name'])){
@unlink($_FILES['file']['tmp_name']);
die('文件上传失败!<br/>请重新上传。<br/><ahref="pfabu.html">返回</a>');
}
//如果文件移动失败,则显示错误信息
//这样就不会导致数据库存储正常,但文件上传失败的情况了
elseif(!move_uploaded_file($_FILES['file']['tmp_name'],$file_move)){
@unlink($_FILES['file']['tmp_name']);
die('文件上传失败!<br/>请重新上传。<br/><ahref="pfabu.html">返回</a>');
}
//这里将重命名后的文件名与原文件名储存在同一个字段中,用竖线(|)隔开
//读取时只需要用explode()分开就可以了
if($mysql=mysql_query("INSERTINTOproct(pkind,pname,ppicture,pshow)VALUES('{$pkind}','{$pname}','{$file_move}|{$_FILES['file']['name']}','{$pshow}')")){
//显示文件上传信息
echo'Upload:',$filename_upload,'<br/>';
echo'Size:',strval($_FILES['file']['size']/1024.0),'KB<br/>';
echo'Storedin:',$file_move,'<br/>';
echo'<ahref="pfabu.html">返回</a>';
echo'<script>alert("success");</script>';
}
//如果存入数据库时失败
//则显示错误信息
else{
@unlink($_FILES['file']['tmp_name']);
die('文件上传失败!<br/>请重新上传。<br/><ahref="pfabu.html">返回</a>');
}
这样就可以了。
由于没有测试,代码难免会出现一些错误,请随意指出,谢谢!
另外,您还应该考虑到不同用户上传同一个文件名的文件的情况,最好是为每个用户单独分配一个文件夹。
而且,当一个文件夹下的文件过多(>300)时,会导致读写速度变慢,这一点要注意。
解决:
当一个用户的文件夹下文件有300个时,用户再上传文件,就将新的文件保存在另一个文件夹中(如:用户名加上这个用户已有的文件夹数量)。
如果还有后续问题,可以联系我的邮箱:
[email protected]
谢谢!