Полагаю, вы не читали комментарии.Хотя я решил показать вам пример процедурным способом.Должно быть легко адаптировать функции к вашей архитектуре кода (возможно, MVC).
Отправной точкой - наиболее важной - является нормализация массива $_FILES
.Лучше всего (и легко) это описано в PSR-7: 1.6 Загруженные файлы - достаточно, если вы прочтете и поймете первые два абзаца и первые два блока кода.После нормализации остальные шаги могут быть применены интуитивно: каждый файл загружается и сохраняется как запись в таблице базы данных (если при загрузке не возникает ошибка).
Код пытаетсязагрузить несколько файлов.Если проблема возникает при загрузке файла (из многих) - например, макс.превышен размер, или недопустимое расширение, и т. д. - тогда для этого файла отображается соответствующее сообщение об ошибке, и файл не сохраняется - ни в файловой системе, ни в базе данных.Другие файлы, процесс загрузки которых не вызывает ошибок, сохраняются.Другими словами: только когда все файлы успешно загружены и сохранены, отображается сообщение об успехе.В противном случае отображается список сообщений об ошибках (только) «проблемных» файлов.
Вы можете запустить код как есть.Все файлы находятся в одном каталоге.
Я не знаю, какой у вас параметр $name
.Поэтому я просто использовал имя файла.
upload.php
<?php
require_once 'config.php';
require 'connection.php';
require_once 'functions.php';
$allFilesUploadedAndSaved = FALSE;
// Operations upon form submission.
if (isset($_POST['submit'])) {
if ($_FILES) {
// Normalize the posted files array.
$normalizedFiles = normalizeUploadedFiles($_FILES['files']);
// Upload and save each file.
foreach ($normalizedFiles as $normalizedFile) {
$uploadedAndSaved = uploadAndSaveFile($connection, $normalizedFile);
if ($uploadedAndSaved !== TRUE) {
$errors[] = $uploadedAndSaved;
}
}
if (!isset($errors)) {
$allFilesUploadedAndSaved = TRUE;
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
<meta charset="UTF-8" />
<!-- The above 3 meta tags must come first in the head -->
<title>Demo - Upload multiple files</title>
<!-- CSS assets -->
<link href="upload.css" type="text/css" rel="stylesheet">
</head>
<body>
<div class="page-container">
<form action="" method="post" enctype="multipart/form-data">
<div class="messages">
<?php
if (isset($errors)) {
foreach ($errors as $error) {
?>
<div class="message danger">
<?php echo $error; ?>
</div>
<?php
}
} elseif ($allFilesUploadedAndSaved) {
?>
<div class="message success">
All files successfully uploaded.
</div>
<?php
}
?>
</div>
<div class="form-group">
<label for="myFiles">My Files</label>
<input type="file" id="myFiles" name="files[]" multiple class="form-control">
</div>
<div class="form-group">
<button type="submit" id="submit" name="submit" value="upload">
Upload
</button>
</div>
</form>
</div>
</body>
</html>
functions.php
<?php
/**
* Normalize the uploaded files array.
*
* NB: Read the link!
*
* @link https://www.php-fig.org/psr/psr-7/#16-uploaded-files PSR-7: 1.6 Uploaded files.
* @param array $files Uploaded files array.
* @return array Normalized files array.
*/
function normalizeUploadedFiles($files) {
$normalizedFiles = [];
foreach ($files as $filesKey => $filesItem) {
foreach ($filesItem as $itemKey => $itemValue) {
$normalizedFiles[$itemKey][$filesKey] = $itemValue;
}
}
return $normalizedFiles;
}
/**
* Upload and save an uploaded file.
*
* @param PDO $connection Db connection.
* @param array $file The file to upload.
* @return string|TRUE TRUE if the file upload is successful, a corresponding error message otherwise.
*/
function uploadAndSaveFile($connection, $file) {
$name = $file['name'];
$type = $file['type'];
$tmpName = $file['tmp_name'];
$error = $file['error'];
$size = $file['size'];
/*
* Check for upload errors.
*
* @todo Return a description message corresponding to the specific error code!
* @link https://secure.php.net/manual/en/features.file-upload.errors.php Error Messages Explained.
*/
if ($error !== UPLOAD_ERR_OK) {
return sprintf('An error occured regarding the file %s. Error code: %s'
, $name
, $error
);
}
// Validate the file size.
if ($size > UPLOAD_MAX_FILE_SIZE) {
return sprintf('The size of the file "%s" exceeds the maximal allowed size (%s Byte).'
, $name
, UPLOAD_MAX_FILE_SIZE
);
}
// Validate the file type.
if (!in_array($type, UPLOAD_ALLOWED_MIME_TYPES)) {
return sprintf('The file "%s" is not of a valid MIME type. Allowed MIME types: %s.'
, $name
, implode(', ', UPLOAD_ALLOWED_MIME_TYPES)
);
}
$nameParts = explode('.', $name);
$extension = strtolower(end($nameParts));
// @todo Find a better way to generate a unique filename!
$uniqueName = substr(md5(time()), 0, 10) . '.' . $extension;
$uploadPath = rtrim(UPLOAD_DIR, '/') . '/' . $uniqueName;
// Create the upload directory.
createDirectory(rtrim(UPLOAD_DIR, '/'));
// Move the file to the new location.
if (!move_uploaded_file($tmpName, $uploadPath)) {
return sprintf('The file "%s" could not be moved to the specified location.'
, $name
);
}
// Save the file.
saveFile($connection, $name, $uploadPath);
return TRUE;
}
/**
* Save a file.
*
* @param PDO $connection Db connection.
* @param string $name File name.
* @param string $path File path.
* @return void
*/
function saveFile($connection, $name, $path) {
$sql = 'INSERT INTO name (
name,
image
) VALUES (
:name,
:image
)';
$statement = $connection->prepare($sql);
$statement->execute([
':name' => $name,
':image' => $path,
]);
}
/**
* Create a directory at the specified path.
*
* @param string $path Directory path.
* @return void
*/
function createDirectory($path) {
if (file_exists($path) && !is_dir($path)) {
throw new UnexpectedValueException(
'The upload directory can not be created because a file having the same name already exists!'
);
}
if (!is_dir($path)) {
mkdir($path, 0777, TRUE);
}
}
config.php
<?php
define('UPLOAD_DIR', 'upload/');
define('UPLOAD_MAX_FILE_SIZE', 10485760); // 10MB.
define('UPLOAD_ALLOWED_MIME_TYPES', [
'image/jpeg',
'image/png',
'image/gif',
]);
connection.php
<?php
/*
* This page contains the code for creating a PDO connection instance.
*/
// Db configs.
define('HOST', 'localhost');
define('PORT', 3306);
define('DATABASE', 'tests');
define('USERNAME', 'root');
define('PASSWORD', 'root');
define('CHARSET', 'utf8');
// Error reporting.
error_reporting(E_ALL);
ini_set('display_errors', 1); /* SET IT TO 0 ON A LIVE SERVER! */
/*
* Create a PDO instance as db connection to db.
*
* @link http://php.net/manual/en/class.pdo.php
* @link http://php.net/manual/en/pdo.constants.php
* @link http://php.net/manual/en/pdo.error-handling.php
* @link http://php.net/manual/en/pdo.connections.php
*/
$connection = new PDO(
sprintf('mysql:host=%s;port=%s;dbname=%s;charset=%s', HOST, PORT, DATABASE, CHARSET)
, USERNAME
, PASSWORD
, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => FALSE,
PDO::ATTR_PERSISTENT => FALSE,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]
);
upload.css
body {
margin: 0;
padding: 20px;
}
.page-container {
padding: 30px;
background-color: #f4f4f4;
}
.messages {
margin-bottom: 20px;
}
.message {
padding: 10px;
margin-bottom: 10px;
border: 1px solid transparent;
}
.success {
color: #3c763d;
border-color: #d6e9c6;
background-color: #dff0d8;
}
.danger {
color: #a94442;
border-color: #ebccd1;
background-color: #f2dede;
}
.warning {
color: #8a6d3b;
border-color: #faebcc;
background-color: #fcf8e3;
}
form {
width: 400px;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: inline-block;
min-width: 40px;
}
button {
padding: 7px 10px;
margin: 10px;
display: block;
color: #fff;
font-size: 14px;
border: none;
background-color: #8daf15;
}