如何修改现有PHP商品上传代码实现多文件上传功能
Hey there! Let's tackle this multi-file upload conversion step by step, and first fix some critical security issues in your existing code that you’ll definitely want to address.
First: Fix the Critical SQL Injection Vulnerability
Your original code directly concatenates user input from $_POST into SQL statements, which is a high-risk SQL injection vulnerability. We'll rewrite all database interactions using prepared statements to mitigate this—this is non-negotiable for production code.
Second: Adapt for Multi-File Uploads
To support multiple files, your HTML form's file input needs to use the multiple attribute and array syntax for the name:
<input type="file" name="file[]" multiple accept="image/*">
This makes $_FILES["file"] an array containing all uploaded files instead of a single file object.
Recommended Database Setup (Scalable)
Instead of cramming multiple filenames into a single Image column (which is hard to maintain long-term), create a separate table to link products to their images:
CREATE TABLE ProductImages ( ImageID INT AUTO_INCREMENT PRIMARY KEY, ProductID INT NOT NULL, Filename VARCHAR(255) NOT NULL, FOREIGN KEY (ProductID) REFERENCES Product(ProductID) );
This follows proper database normalization and makes it easy to add/remove images later.
Full Modified Code
Here's the refactored code that supports multi-file uploads, fixes SQL injection, and uses the scalable database setup:
<?php include "DbConnect.php"; $db = new DbConnect(); $conn = $db->connect(); // Insert product first (using prepared statement to avoid SQL injection) $sql = "INSERT INTO Product(sku, ItemName, ItemDescription, Quantity, PostDate, ItemPrice, Accountemail, Category) VALUES(?, ?, ?, ?, ?, ?, ?, ?)"; $stmt = $conn->prepare($sql); $stmt->bind_param("sssissss", $_POST["sku_no"], $_POST["item_name"], $_POST["item_desc"], $_POST["qty"], $_POST["date_of_sale"], $_POST["price"], $_POST["Accountemail"], $_POST["category"] ); if ($stmt->execute()) { $productId = $conn->insert_id; $uploadedFiles = []; // Create images directory if it doesn't exist if (!file_exists("images")) { mkdir("images", 0777, true); } // Handle multi-file uploads if (!empty($_FILES["file"]["name"][0])) { // Check if any files were uploaded for ($i = 0; $i < count($_FILES["file"]["name"]); $i++) { $photoName = $_FILES["file"]["name"][$i]; $photoTmpName = $_FILES["file"]["tmp_name"][$i]; $photoError = $_FILES["file"]["error"][$i]; // Skip files that failed to upload if ($photoError !== UPLOAD_ERR_OK) { continue; } // Generate a unique filename to avoid overwriting existing files $filename = time() . '_' . uniqid() . '_' . basename($photoName); $filePath = "images/" . $filename; // Move the uploaded file to the target directory if (move_uploaded_file($photoTmpName, $filePath)) { $uploadedFiles[] = $filename; // Insert image record into the ProductImages table $imageSql = "INSERT INTO ProductImages(ProductID, Filename) VALUES(?, ?)"; $imageStmt = $conn->prepare($imageSql); $imageStmt->bind_param("is", $productId, $filename); $imageStmt->execute(); $imageStmt->close(); } } } $data = array( 'message' => "Product added successfully with " . count($uploadedFiles) . " images", 'success' => "1", 'uploaded_images' => $uploadedFiles ); echo json_encode($data); } else { $data = array( 'message' => "Product not added: " . $stmt->error, 'success' => "0" ); echo json_encode($data); } // Clean up database connections $stmt->close(); $conn->close(); ?>
Key Changes Explained
- SQL Injection Protection: All database operations use
prepare()andbind_param()to safely handle user input. - Multi-File Handling: Loops through the
$_FILES["file"]array to process each uploaded file individually, skipping any that had upload errors. - Unique Filenames: Uses
time()+uniqid()to generate unique filenames, preventing file overwrites. - Scalable Image Storage: Links products to images via a separate table, making future maintenance (like deleting specific images) much easier.
- Transparent Feedback: Returns the number of successfully uploaded images in the JSON response for debugging.
内容的提问来源于stack exchange,提问作者Josh Sayles

