您好,这个是 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个时,用户再上传文件,就将新的文件保存在另一个文件夹中(如:用户名加上这个用户已有的文件夹数量)。
如果还有后续问题,可以联系我的邮箱:
[email protected]谢谢!