今天使用了 thinkphp 的图片批量上传发现 同时上传三个文件的状况下 只存储了两个文件缺失一个文件,调试发现 生成文件名时 生成出一样的名字致使文件被覆盖.php
视图thinkphp
<form action="/index/index/upload" enctype="multipart/form-data" method="post">
<input type="file" name="image[]" /> <br>
<input type="file" name="image[]" /> <br>
<input type="file" name="image[]" /> <br>
<input type="submit" value="上传" />
</form>
复制代码
控制器框架
public function upload(){
// 获取表单上传文件
$files = request()->file('image');
foreach($files as $file){
// 移动到框架应用根目录/uploads/ 目录下
$info = $file->move( '../uploads');
if($info){
// 成功上传后 获取上传信息
// 输出 jpg
echo $info->getExtension();
// 输出 42a79759f284b767dfcb2a0197904287.jpg
echo $info->getFilename();
}else{
// 上传失败获取错误信息
echo $file->getError();
}
}
复制代码
}函数
上述代码在move 过程当中直接生成了文件名 , 看下是怎么生成文件名的post
/thinkphp/library/think/File.php 自动 生成文件名的方法是autoBuildNameui
protected function autoBuildName()
{
if ($this->rule instanceof \Closure) {
$savename = call_user_func_array($this->rule, [$this]);
} else {
switch ($this->rule) {
case 'date':
$savename = date('Ymd') . DIRECTORY_SEPARATOR . md5(microtime(true));
break;
default:
if (in_array($this->rule, hash_algos())) {
$hash = $this->hash($this->rule);
$savename = substr($hash, 0, 2) . DIRECTORY_SEPARATOR . substr($hash, 2);
} elseif (is_callable($this->rule)) {
$savename = call_user_func($this->rule);
} else {
$savename = date('Ymd') . DIRECTORY_SEPARATOR . md5(microtime(true));
}
}
}
return $savename;
}
复制代码
$this->rule 默认值 date 因此生成 文件名的是this
$savename = date('Ymd') . DIRECTORY_SEPARATOR . md5(microtime(true));
复制代码
md5 加密 当前微秒浮点数加密
在循环的时候在同一时间调用了该方法因此生成了 一样的文件名spa
生成文件名的规则能够传入回调, 本身实现一个 生成的回调函数调试
在项目根目录的common.php 文件中 建立一个公共函数
if (!function_exists('autoBuild')) {
/**
* /*
* 自定义生成文件名生成规则
* thinkphp 框架采用微秒时间戳生成致使批量上传时生成重复名称
*
* @param $rule 加密方法
* @return string
*/
function autoBuild($rule='sha256'){
if (!in_array($rule, hash_algos())) {
$rule='md5';
}
$uuid=guid();
$hash=hash($rule, time().mt_rand(1000,9999).$uuid);
$savename = date('Ymd') . DIRECTORY_SEPARATOR . substr($hash, 2,36);
return $savename;
}
}
/**
* 生成惟一ID
*/
if (!function_exists('guid')) {
function guid()
{
if (function_exists('com_create_guid')) {
return com_create_guid();
} else {
mt_srand((double)microtime() * 10000);//optional for php 4.2.0 and up.
$charid = strtoupper(md5(uniqid(rand(), true)));
$hyphen = chr(45);// "-"
$uuid = chr(123)// "{"
. substr($charid, 0, 8) . $hyphen
. substr($charid, 8, 4) . $hyphen
. substr($charid, 12, 4) . $hyphen
. substr($charid, 16, 4) . $hyphen
. substr($charid, 20, 12)
. chr(125);// "}"
return $uuid;
}
}
}
复制代码
public function upload(){
// 获取表单上传文件
$files = request()->file('image');
foreach($files as $file){
// 移动到框架应用根目录/uploads/ 目录下 使用 autoBuild 构建文件名
$info = $file->rule('autoBuild')->move( '../uploads');
if($info){
// 成功上传后 获取上传信息
// 输出 jpg
echo $info->getExtension();
// 输出 42a79759f284b767dfcb2a0197904287.jpg
echo $info->getFilename();
}else{
// 上传失败获取错误信息
echo $file->getError();
}
}
}
复制代码