我正在尝试为电子商务网站的产品上传多张图片。想法是在将图像保存在service_images表中的同时将服务名称保存在services表中,但是每当我运行php文件时,它都会将服务上载到services表,但是只将一个图像上载到service_images表,而不是全部图像。如何才能将其上传到服务表中的一项服务,以及在service_images表中上传该服务的多张图像?
下面是我的代码:
add-service.inc.php
<?php
if (isset($_POST['add-service'])) {
require 'config.php';
$shop_name = mysqli_real_escape_string($conn, $_POST['shop_name']);
$service_cat = mysqli_real_escape_string($conn, $_POST['service_cat']);
$service_name = mysqli_real_escape_string($conn, $_POST['service_name']);
$service_desc = mysqli_real_escape_string($conn, $_POST['service_desc']);
$service_price = mysqli_real_escape_string($conn, $_POST['service_price']);
$service_type = mysqli_real_escape_string($conn, $_POST['service_type']);
$service_images = $_FILES['service_images'];
if (empty($shop_name) || empty($service_cat) || empty($service_name) || empty($service_desc) || empty($service_price) || empty($service_type)) {
header('Location: ../services.php?error=emptyFields');
exit();
} elseif (!preg_match('/^[a-zA-Z0-9]*$/', $shop_name) && !preg_match('/^[a-zA-Z0-9\s]*$/', $service_name) && !preg_match('/^[a-zA-Z0-9\s \. \-]*$/', $service_desc) && !preg_match('/^[0-9\.]*$/', $service_price) && !preg_match('/^[a-zA-Z0-9\s \.]*$/', $service_type)) {
header('Location: ../services.php?error=invalidInputs');
exit();
} elseif (!preg_match('/^[a-zA-Z0-9]*$/', $shop_name)) {
header('Location: ../services.php?error=invalidShopName');
exit();
} elseif (!preg_match('/^[a-zA-Z0-9\s]*$/', $service_name)) {
header('Location: ../services.php?error=invalidserviceName');
exit();
} elseif (!preg_match('/^[a-zA-Z0-9\s \. \-]*$/', $service_desc)) {
header('Location: ../services.php?error=invalidDescription');
exit();
} elseif (!preg_match('/^[0-9\.]*$/', $service_price)) {
header('Location: ../services.php?error=invalidPrice');
exit();
} elseif (!preg_match('/^[a-zA-Z0-9\s \.]*$/', $service_type)) {
header('Location: ../services.php?error=invalidStyle');
exit();
} else {
foreach ($_FILES["service_images"]["tmp_name"] as $key => $tmp_name) {
$file_name = $_FILES["service_images"]["name"][$key];
$file_type = $_FILES["service_images"]["type"][$key];
$file_tempName = $_FILES["service_images"]["tmp_name"][$key];
$file_error = $_FILES["service_images"]["error"][$key];
$file_size = $_FILES["service_images"]["size"][$key];
$a = count($_FILES['service_images']['name']);
for ($i = 0; $i < $a; $i++) {
$fileExt = explode('.', $file_name);
$fileActualExt = strtolower(end($fileExt));
$allowed = array('jpg', 'png', 'jpeg');
if (in_array($fileActualExt, $allowed)) {
if ($file_error === 0) {
if ($file_size <= 15000000) {
$newFileName = preg_replace('/\s+/', '', $service_name) . $i . '.' . $fileActualExt;
echo $newFileName . "<br>";
$fileDestination = '../../services/' . $newFileName;
$sql_images = "INSERT INTO service_images (shop_name, service_name) VALUES ('$shop_name', '$service_name')";
$result = mysqli_query($conn, $sql_images);
$sql = "INSERT INTO services (shop_name, service_cat, service_name, service_desc, service_price, service_type) VALUES (?,?,?,?,?,?)";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
header("Location: ../services.php?error=SaveError");
exit();
} else {
mysqli_stmt_bind_param($stmt, 'ssssss', $shop_name, $service_cat, $service_name, $service_desc, $service_price, $service_type);
mysqli_stmt_execute($stmt);
// move_uploaded_file($file_tempName = $_FILES["service_images"]["tmp_name"][$i], $fileDestination);
header("Location: ../services.php?success");
exit();
}
} else {
header('Location: ../services.php?error=invalidSize');
exit();
}
} else {
header('Location: ../services.php?error=invalidImage');
exit();
}
} else {
header('Location: ../services.php?error=invalidImageType');
exit();
}
}
}
}
}
表格
<form action="../admin/includes/add-service.inc.php" method="post" enctype="multipart/form-data">
<input type="text" name="shop_name" id="shopName" class="form-input" placeholder="Shop Name">
<select name="service_cat" id="serviceCat" class="form-input">
<option> -- select category -- </option>
<?php
$sql = "SELECT * FROM service_category";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) > 0) {
while ($row = mysqli_fetch_assoc($result)) {
?>
<option value="<?php echo $row['service_cat'] ?>"><?php echo $row['service_cat'] ?></option>
<?php
}
}
?>
</select>
<input type="text" name="service_name" id="serviceName" class="form-input" placeholder="Service Name">
<textarea name="service_desc" id="service_desc" cols="1" rows="5" placeholder="Description" class="form-input"></textarea>
<input type="text" name="service_price" id="servicePrice" class="form-input" placeholder="Service Price">
<input type="text" name="service_type" id="serviceType" class="form-input" placeholder="Service Type">
<hr>
<label for="serviceImages">*Select all pictures for your service</label>
<input type="file" name="service_images[]" id="serviceImages" class="form-input" multiple>
<button type="submit" class="btn-add" name="add-service">Add Service</button>
</form>
答案 0 :(得分:0)
首先,您有两次相同的循环。首先是foreach,然后是for。由于您需要$ _FILES这种奇怪的数组类型中的数字键,因此最好的方法是仅使用for循环。 这些双循环已经非常混乱,例如,如果其中一个文件有问题,可能会导致意外问题。
但是,您的主要问题是,您基本上只检查一张图像,然后将其上传。如果验证过程或成功失败了,它的末尾将有exit();
。它不仅杀死循环,而且杀死整个脚本。您不允许第二个图像循环继续进行,因为第一个图像循环会杀死它..无论是成功还是错误。
解决方案是等待循环完成(在循环括号后添加代码),然后在其中放置与成功相关的代码。如果在循环内检测到错误,则脚本永远不会走那么远。
我不知道您实际上是如何将图像链接到服务的,但是我试图清理您的代码并使顺序正确。我也尽力解释了原因和地点。希望您对此有所了解,甚至更好,找到更好的选项来优化代码:
// TESTING: Lets see what is inside post values:
echo '<b>$_POST values</b><pre>'; print_r($_POST); echo '</pre>';
// TESTING: Lets see what is inside the files values:
echo '<b>$_FILES values</b><pre>'; print_r($_FILES); echo '</pre>';
// Above is for testing only..
// Probably better place to load important configs:
require 'config.php';
// Since these are the conditions for uploads, then they are global:
// no need for them to be inside the loop:
$allowed = array('jpg', 'png', 'jpeg');
// Maximum allowed filesize:
$max_allowed_file_size = 15000000; // which is 15mb
// We detect the submit buttons trigger name:
if (isset($_POST['add-service'])) {
// Do the escape thingy:
// NOTE: You should be using some mysqli class for database handling:
$shop_name = mysqli_real_escape_string($conn, $_POST['shop_name']);
$service_cat = mysqli_real_escape_string($conn, $_POST['service_cat']);
$service_name = mysqli_real_escape_string($conn, $_POST['service_name']);
$service_desc = mysqli_real_escape_string($conn, $_POST['service_desc']);
$service_price = mysqli_real_escape_string($conn, $_POST['service_price']);
$service_type = mysqli_real_escape_string($conn, $_POST['service_type']);
$service_images = $_FILES['service_images'];
// Lets deal with the errors before going forward with the rest of the script:
// You don't need elseif here, because your callback is to redirect and exit anyways..
if (empty($shop_name) || empty($service_cat) || empty($service_name) || empty($service_desc) || empty($service_price) || empty($service_type)) {
header('Location: ../services.php?error=emptyFields');
exit();
}
if (!preg_match('/^[a-zA-Z0-9]*$/', $shop_name) && !preg_match('/^[a-zA-Z0-9\s]*$/', $service_name) && !preg_match('/^[a-zA-Z0-9\s \. \-]*$/', $service_desc) && !preg_match('/^[0-9\.]*$/', $service_price) && !preg_match('/^[a-zA-Z0-9\s \.]*$/', $service_type)) {
header('Location: ../services.php?error=invalidInputs');
exit();
}
if (!preg_match('/^[a-zA-Z0-9]*$/', $shop_name)) {
header('Location: ../services.php?error=invalidShopName');
exit();
}
if (!preg_match('/^[a-zA-Z0-9\s]*$/', $service_name)) {
header('Location: ../services.php?error=invalidserviceName');
exit();
}
if (!preg_match('/^[a-zA-Z0-9\s \. \-]*$/', $service_desc)) {
header('Location: ../services.php?error=invalidDescription');
exit();
}
if (!preg_match('/^[0-9\.]*$/', $service_price)) {
header('Location: ../services.php?error=invalidPrice');
exit();
}
if (!preg_match('/^[a-zA-Z0-9\s \.]*$/', $service_type)) {
header('Location: ../services.php?error=invalidStyle');
exit();
}
// Nothing happened above, so that means the form validation should be fine and we can go forward with the images:
// So as in your script, we count the images:
$a = count($_FILES['service_images']['name']);
// Now we do a "numeric loop", not an array loop, which is foreach:
for ($i = 0; $i < $a; $i++) {
// Since we have the key as numeric now, we can do what you did before, but without the foreach loop:
$file_name = $_FILES['service_images']['name'][$i];
$file_type = $_FILES['service_images']['type'][$i];
$file_tempName = $_FILES['service_images']['tmp_name'][$i];
$file_error = $_FILES['service_images']['error'][$i];
$file_size = $_FILES['service_images']['size'][$i];
// Get the file extension:
// NOTE: This is not good, as you should really check the mime type of the file, not the extension.
$fileActualExt = strtolower(end(explode('.', $file_name)));
// TESTING: We check print out the data to make sure, that all looks fine:
echo 'File with the key: ' . $i .' -- $file_name: ' . $file_name . '; $file_type: ' . $file_type . '; $file_tempName: ' . $file_tempName . '; $file_error: ' . $file_error . '; $file_size: ' . $file_size . '<br>';
// Instead of making the code ugly, lets deal with errors, by killing the script before
// NOTE: This is not good approach, you should be using Exceptions:
// https://www.php.net/manual/en/language.exceptions.php
// Check if the file extension is NOT in the allowed array
if (!in_array($fileActualExt, $allowed)) {
// Redirect:
header('Location: ../services.php?error=invalidImageType');
// Kill the script:
exit('invalidImageType');
}
// Check if the file had an error:
if ($file_error) {
// Redirect:
header('Location: ../services.php?error=invalidImage');
// Kill the script:
exit('invalidImage');
}
// Check if the image bytes are BIGGER > then max allowed file size variable:
if ($file_size > $max_allowed_file_size) {
// Redirect:
header('Location: ../services.php?error=invalidSize');
// Kill the script:
exit();
}
// At this stage, hopefully, there has not been any errors above and we can deal with file freely:
// Make new file name:
$newFileName = preg_replace('/\s+/', '', $service_name) . $i . '.' . $fileActualExt;
// echo $newFileName . "<br>";
// Set the new destination:
$fileDestination = '../../services/' . $newFileName;
// Lets move the file already.
// NOTE: Make sure that you have some bash code from server side, that deletes outdated / old temp files, so they dont take space:
move_uploaded_file($file_tempName = $_FILES["service_images"]["tmp_name"][$i], $fileDestination);
// Insert the image to database:
// NOTE: Im not sure about your specific code, but just this is there location for that:
$sql_images = "INSERT INTO service_images (shop_name, service_name) VALUES ('$shop_name', '$service_name')";
$result = mysqli_query($conn, $sql_images);
// PROBLEM: This is where you originally had the success message redirect and exit.
// This means, you KILL the script and there for the loop.
// But you have to understand, that you have two images or more, so the loop has to continue freely,
// and you can do this sort of stuff at after the loop!
//
// header("Location: ../services.php?success");
// exit();
}
// If nothing happened above, then the image uploads went trough nicely and we can deal with success messages or adding the service itself:
// I have not used mysqli stmpt before, so I have no idea what is going on in this area..:
// .. but this the locatin to deal with the services as this is the parent and the children are above.
$sql = "INSERT INTO services (shop_name, service_cat, service_name, service_desc, service_price, service_type) VALUES (?,?,?,?,?,?)";
$stmt = mysqli_stmt_init($conn);
// I don't think you need this at all, but whatever:
// Shouldnt this be above
if (!mysqli_stmt_prepare($stmt, $sql)) {
// Redirect:
header("Location: ../services.php?error=SaveError");
// Kill the script:
exit();
}
// This is adding the service I assume, it has to be outside the loop, as single submit = single service. But images are multiple.
mysqli_stmt_bind_param($stmt, 'ssssss', $shop_name, $service_cat, $service_name, $service_desc, $service_price, $service_type);
mysqli_stmt_execute($stmt);
// This is where you can have the success redirect and exit, as this is after the loop:
header("Location: ../services.php?success");
exit();
}
注释:
<input type="file" name="service_images[]" multiple accept=".jpg, .png, .jpeg">
(多个accept =“。jpg,.png,.jpeg” )形式,不允许用户选择其他任何扩展名。 您还可以对所有图像使用“图像”值。