【问题标题】:Check if image exists - database or file lookup?检查图像是否存在 - 数据库或文件查找?
【发布时间】:2021-02-05 18:30:40
【问题描述】:

我根据文件内容对文件名进行哈希处理,并将此名称引用存储在数据库中,并将文件存储在服务器上。

通过检查数据库中的名称或检查服务器上是否存在文件来检查重复文件(因此不会重新上传)会更有效(更快)吗?

会有 1000 多个文件。

【问题讨论】:

  • 数据库通常比文件系统快得多,所以我想说:检查数据库。

标签: php mysql


【解决方案1】:

我遇到了同样的问题,我们有大约 40k 图像,并且重复在我们的服务器上加载很重,尤其是图像许可证管理,因为必须多次将相同的许可证添加到同一个图像。

我建议进行数据库查找。随着您的文件集合的增长,它的速度要快得多。 40k 表扫描大约需要 20 毫秒。磁盘上的 40k 文件搜索在几秒钟内运行,这很快就令人讨厌。

为了解决这个问题,我们更改了图像的上传方式,这样我们就不会得到重复的文件,而是会得到多个引用磁盘上相同物理文件的数据库记录。这使我们可以更快地查找文件数据,而无需“文件”甚至不知道实际文件在哪里。 我们也不会将文件存储为原始文件名,而是基于日期和时间的十六进制哈希,因此我们不会得到冲突的文件名,也不会因特殊字符、空格等而导致交付问题......并存储用于查找目的的数据库字段中的原始文件名。

我们的图像将其“元数据”存储在数据库中,具有十六进制文件名和“原始”文件名。检查这个数据库真的很快,然后在有匹配/关系时检索文件链接。这也允许检查此文件是否已上传,因为您无需使用 alt 图片扫描整个目录结构,这可能会占用大量时间。

这是我使用的代码,你可以使用类似的东西。请注意,这是使用 laravel 的 eloquent,但在纯 mysql 中复制相当容易。

首先你得到一个实例来查询文件模型表。 然后检查一个文件,其中原始文件名、文件大小、内容类型和其他不应更改的元数据相同。 如果它们相同,请将您的文件条目复制为原始条目(在我的情况下,这允许修改每个参考的图像标题和描述)

        $file = new $FILE();
        $existingFile = $file->newQuery()->where('file_name',$uploadedFile->getClientOriginalName())
                                ->where('file_size',$uploadedFile->getSize())
                                ->where('content_type',$uploadedFile->getMimeType())
                                ->where('is_public',$fileRelation->isPublic())->limit(1)->get()->first();
        
        
        if($existingFile) {
        
            $file->disk_name = $existingFile->disk_name;
            $file->file_size = $existingFile->file_size;
            $file->file_name = $existingFile->file_name;
            $file->content_type = $existingFile->content_type;
            $file->is_public = $existingFile->is_public;
        }
        else {
            
            $file->data = $uploadedFile;
            $file->is_public = $fileRelation->isPublic();
            
            
        }

那么随着文件被删除,你需要检查它是否是“最后一个”

public function afterDelete()
    {
        try {
            $count = $this->newQuery()->where('disk_name','=',$this->disk_name)
            ->where('file_name','=',$this->file_name)
            ->where('file_size','=', $this->file_size)
            ->count();
            
            if(!$count) {
                $this->deleteThumbs();
                $this->deleteFile();
            }
        }
        catch (Exception $ex) {
            traceLog($ex->getMessage() . '\n' . $ex->getTraceAsString());
        }
    }

【讨论】:

  • 不回答问题。
  • @panthro 现在可以了
  • 答案应该像问题一样,简短而中肯。我们真的不需要所有的背景故事。它过于关注实际答案(这就是人们来这里的原因)
  • @MagnusEriksson 这就是你的意见。你有权这样做。
猜你喜欢
  • 2013-01-13
  • 1970-01-01
  • 2011-07-01
  • 1970-01-01
  • 2011-02-26
  • 1970-01-01
  • 2021-11-30
  • 2014-07-08
  • 2019-06-24
相关资源
最近更新 更多