php 图片上传有个小BUG,求大神解答。以下是我的一些代码

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php 图片上传有个小BUG,求大神解答。以下是我的一些代码相关的知识,希望对你有一定的参考价值。

$link=mysql_connect('localhost','root','123456');
mysql_query("set names 'UTF8'");
mysql_select_db('zhenyu',$link);
$pkind=$_POST['pkind'];
$pname=$_POST['pname'];
$pshow=$_POST['pshow'];
$mysql=mysql_query("insert into product (pkind,pname,ppicture,pshow) values ('".$pkind."','".$pname."','"."product/".$_FILES["file"]["name"]."','".$pshow."')");//上传文件保存在product文件夹
if($mysql)

move_uploaded_file($_FILES["file"]["tmp_name"],"product/".$_FILES["file"]["name"]);
echo "Upload: " . $_FILES["file"]["name"] . "<br />";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
echo "Stored in: " . "product/" . $_FILES["file"]["name"].'<br />';
echo '<a href="pfabu.html">返回</a>';
echo '<script>alert("success");</script>';

如果上传的图片名不超过3个汉字或者包含英文字符,则一切正常。但是如果图片名字数超过3个且只有汉字跟数字,图片不会上传到指定文件夹,其他的输出语句和数据库都还是正常。
这种情况应该是 move_uploaded_file($_FILES["file"]["tmp_name"],"product/".$_FILES["file"]["name"]);这句话没有执行,可是是为什么呢?
怎么才能解决这个问题,求高手指教

您好,这个是 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 /><a href="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 /><a href="pfabu.html">返回</a>');
    
    $ftype = NULL;


$link  = mysql_connect('localhost','root','123456');
mysql_query('set names \\'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-z A-Z 0-9 以及+,/,=
$filename   = base64_encode($filename_upload);
// Base64 编码中有一些非文件名可用的字符,把它们替换掉
$filename   = strtr($filename, array(
        '+' => '.',
        '/' => '_',
        '=' => '-'
    )
);
// 上传后的文件保存在product文件夹
$file_move  = 'product/' . $filename;

// 如果文件已存在,则在文件名后加上-和一个随机数
// 当然,这一部分也可以您自己更改,不会影响结果
if(file_exists($file_move)) 
    $rand             = '-' . strval(rand(0, 9999));
    $file_move       .= $rand;
    $filename_upload .= $rand;
    // 因为 $rand 被其它变量引用,不能直接注销
    // 所以将其赋值为 NULL,也可达到同样的释放内存的效果
    $rand = NULL;


// 判断文件是否是通过 HTTP POST 上传的
// 这可以用来确保恶意用户无法欺骗程序去访问本不该访问的文件,例如/etc/passwd
if (!is_uploaded($_FILES['file']['tmp_name'])) 
    @unlink($_FILES['file']['tmp_name']);
    die('文件上传失败!<br />请重新上传。<br /><a href="pfabu.html">返回</a>');

// 如果文件移动失败,则显示错误信息
// 这样就不会导致数据库存储正常,但文件上传失败的情况了
elseif (!move_uploaded_file($_FILES['file']['tmp_name'], $file_move)) 
    @unlink($_FILES['file']['tmp_name']);
    die('文件上传失败!<br />请重新上传。<br /><a href="pfabu.html">返回</a>');


// 这里将重命名后的文件名与原文件名储存在同一个字段中,用竖线(|)隔开
// 读取时只需要用 explode() 分开就可以了
if($mysql = mysql_query("INSERT INTO product(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 'Stored in: ', $file_move, '<br />';
       echo '<a href="pfabu.html">返回</a>';
       echo '<script>alert("success");</script>';

// 如果存入数据库时失败
// 则显示错误信息
else 
    @unlink($_FILES['file']['tmp_name']);
    die('文件上传失败!<br />请重新上传。<br /><a href="pfabu.html">返回</a>');

这样就可以了。

由于没有测试,代码难免会出现一些错误,请随意指出,谢谢!


另外,您还应该考虑到不同用户上传同一个文件名的文件的情况,最好是为每个用户单独分配一个文件夹。

而且,当一个文件夹下的文件过多(>300)时,会导致读写速度变慢,这一点要注意。

解决:

当一个用户的文件夹下文件有300个时,用户再上传文件,就将新的文件保存在另一个文件夹中(如:用户名加上这个用户已有的文件夹数量)。


如果还有后续问题,可以联系我的邮箱:

blutrex@gmail.com

谢谢!

参考技术A 这个BUG我也碰到过,最简单的办法就是把现在的文件名为短MD5+时间,可以防重名的 参考技术B 上传后重新命个名就不存在这个问题了,即在move_upload_file()那里改一下,不要用原来的文件名,重新命个名字,比如 ‘product/’.time().mt_rand(100, 999).'原来图片的后缀';多说几句呀,依代码看这代码不光是一点小BUG,一般人都不会这么写吧,即不做过滤检测也不是判断是否是真实上传的内容,也不判断上传的是不是图片,这应该是楼主拿来自己写的玩的吧, 参考技术C move_uploaded_file($_FILES["file"]["tmp_name"],"product/".$_FILES["file"]["name"])

没有后缀名

以上是关于php 图片上传有个小BUG,求大神解答。以下是我的一些代码的主要内容,如果未能解决你的问题,请参考以下文章

Java算法bug求大神解答。。明天交作业 急急急急急急

discuz默认头像不显示,求大神解答!

Android调用照相机和百度地图开发,百度地图显示界面覆盖了相机界面,求大神解答?

用Java做的毕业设计里加个虚拟的在线支付功能怎么弄?求大神解答,只要有个虚拟的功能就好。急

.net在图片里怎么加按钮,是一个大图片,里面有按钮,不是给按钮加背景图片。求大神解答

求PHP多图片上传带预览的插件,有demo最好,