【发布时间】:2015-10-31 09:47:09
【问题描述】:
我想在验证其他输入字段的同时验证文件上传。这听起来并不难,但如果我选择一个文件然后提交表单,当其他输入错误存在时,该文件也会临时上传。
所以用户必须修复这个错误,然后必须再次选择文件:(。有没有一种用户友好的实现方式?
我当前的实现大致如下:
我有一个这样的简单表格:
<form method="post" enctype="multipart/form-data">
<input type="text" name="firstname" value="<?php echo $form->getFirstname() ?>" />
<input type="text" name="lastname" value="<?php echo $form->getLastname() ?>" />
<input type="file" name="file" />
<input type="hidden" name="terms" value="false"/>
<input type="checkbox" name="terms" value="terms" <?php if ($form->getTerms() === 'terms') echo 'checked' ?> />
<input type="submit" name="send" value="send" />
</form>
因此,在提交此表单后,所有用户数据(如名字、姓氏和术语)都将被设置和验证,如下所示:
if ( isset($_POST['send']) && $_POST['send'] === 'send' ) {
if ( !\Fox\Validator::isString($_POST['firstname']) ) {
\Fox\Validator::setError(1, 'firstname required');
} else {
$form->setFirstname($_POST['firstname']);
}
// ... other unimportant validations
// validate file upload
if (!isset($_FILES['file']['error']) || is_array($_FILES['file']['error'])) {
\Fox\Validator::setError(10, 'error occurred');
} else {
// check error value
switch ($_FILES['file']['error']) {
// file exists
case UPLOAD_ERR_OK:
// check filesize (max filesize 100mb)
if ($_FILES['file']['size'] > 104857600) {
\Fox\Validator::setError(10, 'max filesize overridden');
} else {
$finfo = new finfo(FILEINFO_MIME_TYPE);
// define allowed mime types
$allowedMimeTypes = array(
'jpg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
'bmp' => 'image/bmp',
'bmp' => 'image/x-ms-bmp',
'bmp' => 'image/x-windows-bmp',
'mov' => 'video/quicktime',
'avi' => 'video/avi',
'avi' => 'video/msvideo',
'avi' => 'video/x-msvideo',
'mp4' => 'video/mp4',
'mpeg' => 'video/mpeg',
'mkv' => 'video/x-matroska',
'flv' => 'video/x-flv',
'wmv' => 'video/x-ms-wmv',
);
if (false === $ext = array_search($finfo->file($_FILES['file']['tmp_name']), $allowedMimeTypes, true)) {
\Fox\Validator::setError(10, 'file not supported');
}
}
break;
case UPLOAD_ERR_NO_FILE:
\Fox\Validator::setError(10, 'no file selected');
break;
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
\Fox\Validator::setError(10, 'filesize overridden');
break;
default:
\Fox\Validator::setError(10, 'error occurred');
}
}
// check if form errors exists
if (empty(\Fox\Validator::getError())) {
// create unique filename
$tmp = sha1_file($_FILES['file']['tmp_name']);
// move file
if (!move_uploaded_file($_FILES['file']['tmp_name'], sprintf('./Files/%s.%s', $tmp, $ext))) {
\Fox\Validator::setError(10, 'error by uploading file');
} else {
header("Location: $successPage");
}
}
}
因此,如果不存在表单错误,则文件将正确上传,并且用户将被重定向到成功页面,但如果由于用户错过了必需的输入字段(如名字)而发生错误,则文件将通过提交上传操作,但未保存,因此用户必须更正错误的输入并再次选择文件。
【问题讨论】:
-
您希望输入选择相同的文件吗?
-
imo,这样做的一种方法是:1) 文件被上传,然后您将其移动到“临时暂存区”,直到您验证所有其他信息。 1 a] 您告诉用户文件上传正常,但正在等待您需要的任何许可。 2)您将其移至“永久区域”。你告诉用户数据验证是好的。这些都是服务器端验证检查。您每隔几个小时清理一次“临时暂存区”。
-
@phplover 是的,但这是不可能的还是我错了?
-
@Ryan 好的,所以我必须将文件移动到临时暂存区域或直接移动到永久区域,但例如当用户忘记设置名字时,文件将是上传到临时或永久登台,用户必须再次检查表单,到目前为止一切顺利。但是我怎样才能防止用户之后上传另一个文件呢?我应该使用像 $fileIsUploaded 这样的布尔标志并检查这个标志是真还是假?
-
如果表单没有发现错误,为什么不直接上传文件?
标签: php validation file-upload