Ajax+PHP多文件上传至数据库问题:BLOB为空及文件读取警告
排查多文件上传至数据库的问题
你遇到的两个问题(文件找不到警告、BLOB字段为空)其实是同一个核心错误导致的,下面一步步帮你分析和修复:
核心错误:使用文件名而非临时文件路径
警告failed to open stream: No such file or directory的根源是:你在file_get_contents里传入了$_FILES["files"]["name"][$i]——这只是用户上传文件的原始名称,并不是文件在服务器上的临时存储路径。PHP会把上传的文件临时存在$_FILES["files"]["tmp_name"][$i]这个位置,必须读取这个路径的文件内容才能获取到正确的二进制数据。
其他潜在问题
- Response变量覆盖:循环里每次迭代都会重置
$response,最终只会返回最后一个文件的处理结果,前面的错误信息会被覆盖。 addslashes的风险:用addslashes处理二进制数据可能导致内容损坏,而且PDO的参数绑定本身已经会自动处理转义,不需要手动添加。- 缺少上传错误的完整判断:只判断了
error > 0,但最好用PHP内置的UPLOAD_ERR_OK常量来准确判断上传是否成功。
修改后的代码
upload.php 修复版本
ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); include_once '../../../connections_multi.php'; $p_id = 1001; // 测试用ID $no_files = count($_FILES["files"]['name']); $response = []; // 用数组存储每个文件的处理结果,避免覆盖 for ($i = 0; $i < $no_files; $i++) { // 先准确判断文件是否上传成功 if ($_FILES["files"]["error"][$i] !== UPLOAD_ERR_OK) { $response[] = "文件 {$i+1} 上传错误: 错误码 " . $_FILES["files"]["error"][$i]; continue; } // 读取服务器临时文件的二进制内容 $file_content = file_get_contents($_FILES["files"]["tmp_name"][$i]); if ($file_content === false) { $response[] = "无法读取文件 {$i+1}: " . $_FILES["files"]["name"][$i]; continue; } // 准备SQL插入语句 $stmt = $db->prepare("INSERT INTO products.battery_lobs (p_id, img) VALUES (?, ?)"); if (!$stmt) { $response[] = "文件 {$i+1} 准备SQL失败: " . $db->error; continue; } // 绑定参数(s=字符串类型ID,b=二进制BLOB数据) if (!$stmt->bind_param("sb", $p_id, $file_content)) { $response[] = "文件 {$i+1} 参数绑定失败: " . $stmt->error; continue; } // 执行插入操作 if (!$stmt->execute()) { $response[] = "文件 {$i+1} 插入数据库失败: " . $stmt->error; } else { $response[] = "文件 {$i+1} 上传成功: " . $_FILES["files"]["name"][$i]; } } // 返回所有文件的处理结果,方便调试 echo json_encode($response);
index.php 小优化(可选)
把Ajax的响应类型改成JSON,这样能更清晰地看到每个文件的处理状态:
function fourthStep(){ var formData = new FormData(); var files = document.getElementById('imagesToUpload').files; for (var x = 0; x < files.length; x++) { formData.append("files[]", files[x]); } $.ajax({ url: 'includes/forms/addProductSteps/BTR/upload.php', dataType: 'json', // 指定响应为JSON类型 cache: false, contentType: false, processData: false, data: formData, type: 'post', success: function (response) { // 把所有结果拼接成字符串弹出 var msg = response.join('\n'); alert(msg); }, error: function (xhr) { alert('请求错误: ' + xhr.responseText); } }); }
额外测试建议
- 确保服务器的临时目录(默认是
/tmp)有读写权限,PHP能正常写入临时文件。 - 检查
battery_lobs表的img字段类型是否为BLOB、MEDIUMBLOB或LONGBLOB,确保能容纳你要上传的文件大小。 - 如果要上传大文件,需要修改
php.ini里的upload_max_filesize和post_max_size参数,设置为合适的值。
内容的提问来源于stack exchange,提问作者Edgars 艩usts
相关产品推荐
相关产品推荐

