PHP+MySQL多文件上传序列化数据被截断问题求助
问题描述
开发基于PHP和MySQL的多文件批量上传应用,将文件路径序列化后存入MySQL数据库。上传1-4个文件时一切正常,但上传超过4个文件时,MySQL会截断序列化后的末尾数据,导致数据失效,无法正常反序列化查看文件。
正常序列化数据(2个文件):
a:2:{i:0;s:22:"uploads/HqihCeKwvR.png";i:1;s:22:"uploads/cQqshZLoNB.png";}
截断后的序列化数据(8个文件):
a:8:{i:0;s:22:"uploads/nQEOmDelCR.png";i:1;s:22:"uploads/qMCJaNsSPl.png";i:2;s:22:"uploads/W0oUaN3GZm.png";i:3;s:22:"uploads/qJEYRkh04I.png";i:4;s:22:"uploads/h1SozRvFZV.png";i:5;s:22:"uploads/bPcJ32yWuC.png";i:6;s:22:"uploads/OURS3jCzIp.jpg";i:7;s:22:"up
相关代码
Upload.php
$qualification = multiple_upload($_FILES["qualification"]); function multiple_upload($file) { $target_dir = "uploads/"; $uploadOk = 1; $countfiles = count($_FILES['qualification']['name']); for ($i = 0; $i < $countfiles; $i++) { $file_name = generateRandomString(); $target_file = $target_dir . basename($_FILES['qualification']['name'][$i]); $imageFileType = strtolower(pathinfo($target_file, PATHINFO_EXTENSION)); $file_path = $target_dir . "" . $file_name . "." . $imageFileType; $qualifications[] = $file_path; // Allow certain file formats if ( $imageFileType != "jpg" || $imageFileType != "png" || $imageFileType != "jpeg" || $imageFileType != "pdf" || $imageFileType != "doc" || $imageFileType != "docx" || $imageFileType != "gif" ) { $imageFileType = $imageFileType; } else { die("Sorry, only JPG, JPEG, PNG & GIF files are allowed."); $uploadOk = 0; } if (move_uploaded_file($_FILES['qualification']['tmp_name'][$i], $file_path)) { echo $file_path; } else { // die("Sorry, there was an error uploading your file."); } } return serialize($qualifications); } function generateRandomString($length = 10) { return substr(str_shuffle(str_repeat($x = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length / strlen($x)))), 1, $length); } $sql = " INSERT INTO staff_info SET qualification = '$qualification '"; if ($conn->query($sql) === TRUE) { echo "successful..."; // header("location: upload_successful.html"); } else { echo "Error: " . $sql . "<br>" . $conn->error; }
View.php
<?php $qualifications = unserialize($row["qualification"]); foreach ($qualifications as $key => $value) { echo '<img src="' . $value . '" style="width: 300px; height: 300px; object-fit:cover" alt=""> <br />'; } ?>
解决方案
核心原因
MySQL表中qualification字段的长度不足,当前大概率为VARCHAR(255)这类短长度类型。当序列化后的字符串超过字段定义长度时,MySQL会自动截断数据,破坏序列化结构,导致无法反序列化。
1. 修改MySQL字段类型/长度
执行SQL语句将字段改为TEXT或LONGTEXT,确保能容纳足够长的序列化字符串:
-- 改用TEXT类型,最大支持65535字符 ALTER TABLE staff_info MODIFY COLUMN qualification TEXT; -- 若需要存储更长内容,使用LONGTEXT(最大支持4GB) -- ALTER TABLE staff_info MODIFY COLUMN qualification LONGTEXT;
2. 修复SQL注入风险与数据存储异常
原代码直接拼接SQL语句存在严重安全隐患,同时特殊字符可能导致存储异常,改用预处理语句:
// 替换原有INSERT代码 $sql = "INSERT INTO staff_info SET qualification = ?"; $stmt = $conn->prepare($sql); $stmt->bind_param("s", $qualification); if ($stmt->execute()) { echo "successful..."; } else { echo "Error: " . $stmt->error; } $stmt->close();
3. 修正文件格式验证逻辑
原逻辑使用||导致所有文件都能通过验证,改为正确的白名单判断:
// 替换原格式验证代码 $allowed_types = ["jpg", "png", "jpeg", "pdf", "doc", "docx", "gif"]; if (!in_array($imageFileType, $allowed_types)) { die("Sorry, only JPG, JPEG, PNG, GIF, PDF, DOC & DOCX files are allowed."); $uploadOk = 0; }
4. 可选:改用JSON存储(更可靠)
序列化数据可读性差且易被破坏,推荐使用JSON格式存储路径数组:
// multiple_upload函数中替换return语句 return json_encode($qualifications); // View.php中替换反序列化代码 $qualifications = json_decode($row["qualification"], true);
JSON格式兼容性更好,若字段长度不足,MySQL会抛出错误而非静默截断,便于排查问题。
内容的提问来源于stack exchange,提问作者etranz
相关产品推荐
相关产品推荐

