为何图片存入数据库的代码无法运行?求助排查
问题描述
花费数小时尝试将用户上传的图片以BLOB(二进制数据)形式存入数据库,但PHP始终无法获取上传文件,一直提示“Please select an image file to upload.”错误。当前逻辑是通过HTML表单获取用户上传的图片,使用AJAX提交数据至PHP后端,由PHP将图片二进制数据存入数据库,但文件始终无法传递到后端。
相关代码
HTML表单代码
<form action="editor.php" class="createBlogForm" autocomplete="off"> <input type="text" name="title" placeholder="Title" class="title"> <?php include 'editor.html'; ?> </div> <div id="catAndSave"> <select name="categoriesOnCreate" class="categoriesOnCreate"> <option value="option1">Option 1</option> <option value="option2" selected="selected">Anderes</option> </select> <div id="coverImageDiv"> <label for="inputTag"> Select Cover Photo <br/> <i class="fa fa-2x fa-camera"></i> <input id="inputTag" type="file" name="image"/> <br/> <span id="imageName"></span> </label> </div> <script> let input = document.getElementById("inputTag"); let imageName = document.getElementById("imageName") input.addEventListener("change", ()=>{ let inputImage = document.querySelector("input[type=file]").files[0]; imageName.innerText = inputImage.name; }) </script> <button type="submit" class="blogSave" onclick="save();">Save</button> </form>
AJAX提交代码
<script> function save(){ var xmlhttp = new XMLHttpRequest(); var content = document.getElementsByClassName('content')[0].innerHTML; var title = document.getElementsByClassName('title')[0].value; var category = document.getElementsByClassName('categoriesOnCreate')[0].value; var data = new FormData(); data.append("content", content); data.append("title", title); data.append("category", category); const queryString = window.location.search; const urlParams = new URLSearchParams(queryString); const id = urlParams.get('id'); xmlhttp.open("POST","editor.php?id=" + id ,true); xmlhttp.send(data); window.location = "http://192.168.56.104/sodablog/editor.php"; }; </script>
PHP处理代码
<?php ini_set('display_errors', '1'); ini_set('display_startup_errors', '1'); error_reporting(E_ALL); session_start(); include 'dbconnect.php'; $content = $_POST['content']; $title = $_POST['title']; $category = $_POST['category']; date_default_timezone_set('Europe/Rome'); $date = date("YmdHis"); $status = 'error'; if(!empty($_FILES["image"]["name"])) { // Get file info $fileName = basename($_FILES["image"]["name"]); $fileType = pathinfo($fileName, PATHINFO_EXTENSION); // Allow certain file formats $allowTypes = array('jpg','png','jpeg','gif'); if(in_array($fileType, $allowTypes)){ $image = $_FILES['image']['tmp_name']; $imgContent = addslashes(file_get_contents($image)); // Insert image content into database $insert = $db->query("INSERT INTO `blog_posts`(`coverImage`) VALUES ('$imgContent');"); if($insert){ $status = 'success'; $statusMsg = "File uploaded successfully."; }else{ $statusMsg = "File upload failed, please try again."; } }else{ $statusMsg = 'Sorry, only JPG, JPEG, PNG, & GIF files are allowed to upload.'; } }else{ $statusMsg = 'Please select an image file to upload.'; } // Display status message echo $statusMsg; $sql = "INSERT INTO `blog_posts`(`created_at`, `last_updated_at`, `content`, `title`, `category`) VALUES('$date', '$date', '$content', '$title', '$category');"; $execution = mysqli_query($conn, $sql) or die("Fehler"); ?>
问题排查与解决方法
1. AJAX未添加上传文件到FormData
核心问题是AJAX创建FormData后,没有将用户选择的图片文件加入其中,导致后端无法获取文件。修改AJAX代码:
function save(event){ // 阻止表单默认提交行为,避免页面提前跳转 event.preventDefault(); var xmlhttp = new XMLHttpRequest(); var content = document.getElementsByClassName('content')[0].innerHTML; var title = document.getElementsByClassName('title')[0].value; var category = document.getElementsByClassName('categoriesOnCreate')[0].value; // 获取用户选择的图片文件 var imageFile = document.getElementById('inputTag').files[0]; var data = new FormData(); data.append("content", content); data.append("title", title); data.append("category", category); // 将图片文件加入FormData if(imageFile) { data.append("image", imageFile); } const queryString = window.location.search; const urlParams = new URLSearchParams(queryString); const id = urlParams.get('id'); xmlhttp.open("POST","editor.php?id=" + id ,true); // 无需手动设置Content-Type,浏览器会自动处理multipart/form-data格式 xmlhttp.send(data); // 等待AJAX请求完成后再跳转页面 xmlhttp.onload = function() { if(xmlhttp.status === 200) { window.location = "http://192.168.56.104/sodablog/editor.php"; } }; };
2. HTML表单缺少文件上传必需属性
上传文件的表单必须设置enctype="multipart/form-data",否则浏览器无法正确编码文件数据。修改form标签:
<form action="editor.php" class="createBlogForm" autocomplete="off" enctype="multipart/form-data">
3. 修复按钮的默认提交行为
原按钮为type="submit",点击会触发表单默认提交,导致AJAX请求被中断。可通过两种方式修复:
- 方法一:修改按钮类型为
button
<button type="button" class="blogSave" onclick="save(event);">Save</button>
- 方法二:在save函数中阻止默认行为(已在上面AJAX代码中实现)
4. 修复PHP代码的SQL注入风险与逻辑问题
原代码存在严重SQL注入风险,且两次插入数据会生成两条独立记录,需合并为一次插入,并使用预处理语句:
<?php ini_set('display_errors', '1'); ini_set('display_startup_errors', '1'); error_reporting(E_ALL); session_start(); include 'dbconnect.php'; // 安全获取POST参数,避免未定义索引错误 $content = $_POST['content'] ?? ''; $title = $_POST['title'] ?? ''; $category = $_POST['category'] ?? ''; date_default_timezone_set('Europe/Rome'); $date = date("YmdHis"); $status = 'error'; $statusMsg = 'Please select an image file to upload.'; // 检查文件是否上传成功 if(!empty($_FILES["image"]["name"]) && $_FILES["image"]["error"] === UPLOAD_ERR_OK) { $fileName = basename($_FILES["image"]["name"]); $fileType = strtolower(pathinfo($fileName, PATHINFO_EXTENSION)); $allowTypes = array('jpg','png','jpeg','gif'); if(in_array($fileType, $allowTypes)){ $imgContent = file_get_contents($_FILES['image']['tmp_name']); // 使用预处理语句防止SQL注入,合并图片与文章数据的插入操作 $stmt = $conn->prepare("INSERT INTO `blog_posts`(`coverImage`, `created_at`, `last_updated_at`, `content`, `title`, `category`) VALUES (?, ?, ?, ?, ?, ?)"); $stmt->bind_param("ssssss", $imgContent, $date, $date, $content, $title, $category); if($stmt->execute()){ $status = 'success'; $statusMsg = "File uploaded successfully."; }else{ $statusMsg = "File upload failed, please try again."; } $stmt->close(); }else{ $statusMsg = 'Sorry, only JPG, JPEG, PNG, & GIF files are allowed to upload.'; } }elseif($_FILES["image"]["error"] !== UPLOAD_ERR_NO_FILE) { // 处理其他上传错误 $statusMsg = 'File upload error: ' . $_FILES["image"]["error"]; } echo $statusMsg; ?>
注:确保dbconnect.php返回的mysqli连接对象为$conn,保持代码中连接对象的一致性。
内容的提问来源于stack exchange,提问作者theCrashinator
相关产品推荐
相关产品推荐

