如果用户将用户数据与文件一起上传(用户数据存储在数据库中,文件存储在文件系统中),关于完整性的最佳做法是什么?
目前,我会使用 PHP 和 PDO 执行类似于以下代码片段的操作(代码未经过测试,但我希望您能理解我的意思)。我不喜欢 User::insert 方法中的保存图像部分。有解决这个问题的好办法吗?
<?php
User::insert($name, $image, $ext);
Class User{
static public function insert($name, $image, $ext){
$conn = DB_config::get();
$conn->beginTransaction();
$sth = $conn->prepare("
INSERT INTO users (name)
values(:name)
;");
$sth->execute(array(
":name" => $name
));
if ($conn->lastInsertId() > -1 && Image::saveImage($image, IMAGE_PATH . $conn->lastInsertId(). $ext))
$conn->commit();
else
$conn->rollback();
return $conn->lastInsertId();
}
}
Class Image{
static public function saveimage($image, $filename){
$ext = self::getExtensionFromFilename($filename);
switch($ext){
case "jpg":
case "jpeg":
return imagejpeg(imagecreatefromstring($image), $filename);
}
return false;
}
?>
最佳答案
试试这个。
将图像保存到工作区的磁盘中。最好保存到 与最终目标位于同一卷上的工作区。 也最好放在单独的目录下。
开始与数据库的事务。
插入您的用户。
在用户 ID 后重命名图像文件。
提交交易。
它所做的是首先执行风险最高的操作,即保存图像。各种各样的事情都可能在这里发生——系统可能会失败,磁盘可能已满,连接可能会关闭。这(可能)是您操作中最耗时的,因此它绝对是风险最高的。
一旦完成,您就开始交易并插入用户。
如果此时系统出现故障,你的insert会被回滚,image会在临时目录中。但是对于您的真实系统,实际上“什么都没有发生”。可以使用自动功能清理临时目录(即重启时清理,清理超过 X 小时/天的所有内容,等等)。文件在此目录中的时间跨度应该很短。
接下来,将图像重命名为它的最终位置。文件重命名是原子的。它们工作或不工作。
如果系统在此之后,用户行将回滚,但文件将在其最终目的地。但是,如果在重新启动后有人试图添加一个新用户,而这个新用户恰好与失败的用户具有相同的用户 ID,则他们上传的图像将简单地覆盖现有的图像——没有伤害,没有犯规。如果不能重新使用用户标识,您将拥有一个孤立的图像。但这可以合理地每周或每月通过自动化程序清理一次。
最后提交事务。
此时一切都在正确的地方。
关于php - 最佳实践数据库事务和在 PHP 中将文件存储到文件系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11657899/