PHP文件上传报错:move_uploaded_file提示访问null数组偏移量
解决PHP文件上传报错:Trying to access array offset on value of type null
问题根源
从你提供的var_dump($_FILES)输出可以看到:
array(1) { ["file"]=> array(6) { ["name"]=> string(11) "MotoGP.pptx" ["full_path"]=> string(11) "MotoGP.pptx" ["type"]=> string(0) "" ["tmp_name"]=> string(0) "" ["error"]=> int(1) ["size"]=> int(0) } }
其中error字段值为1,对应PHP内置常量UPLOAD_ERR_INI_SIZE,说明该pptx文件的大小超过了PHP配置中设置的上传文件大小限制,导致服务器没有生成临时文件,tmp_name因此为空,后续调用move_uploaded_file时触发数组偏移访问错误。
解决步骤
1. 调整PHP上传配置
找到服务器上的php.ini配置文件,修改以下参数:
upload_max_filesize:设置为大于你要上传的最大文件大小,例如:upload_max_filesize = 20Mpost_max_size:该值必须大于upload_max_filesize,例如:post_max_size = 25M
修改完成后,重启你的Web服务器(Apache/Nginx)使配置生效。
2. 完善代码的错误检查逻辑
在处理文件上传前,先检查上传错误状态,避免无效的后续操作。修改后的函数如下:
function dodajTorrent($kategorije) { if (isset($_POST['gumb'])) { $link = open_database_connection(); $vseKategorije = serialize($kategorije); $naslov = $_POST['naslov']; $vsebina = $_POST['vsebina']; $kategorija = $_POST['kategorija']; $file = $_FILES['file']; // 第一步:检查文件上传错误 if ($file['error'] !== UPLOAD_ERR_OK) { $errorMessages = [ UPLOAD_ERR_INI_SIZE => '文件大小超过服务器限制', UPLOAD_ERR_FORM_SIZE => '文件大小超过表单限制', UPLOAD_ERR_PARTIAL => '文件仅部分上传', UPLOAD_ERR_NO_FILE => '未选择文件', UPLOAD_ERR_NO_TMP_DIR => '服务器缺少临时文件夹', UPLOAD_ERR_CANT_WRITE => '无法写入临时文件', UPLOAD_ERR_EXTENSION => 'PHP扩展阻止了文件上传' ]; $errorMsg = isset($errorMessages[$file['error']]) ? $errorMessages[$file['error']] : '未知上传错误'; echo '<script type="text/javascript"> alert("上传错误: ' . $errorMsg . '") </script>'; mysqli_close($link); return; } $filename = $file['name']; $extention = pathinfo($filename, PATHINFO_EXTENSION); if (empty($naslov) || empty($vsebina) || $kategorija == 0) { echo '<script type="text/javascript"> alert("You left empty fields!") </script>'; } else { // 优化文件扩展名检查 $allowedExts = ["torrent", "docx", "doc", "rtf", "xls", "xlsx", "ppt", "pptx", "pdf", "7z", "zip", "rar"]; if (!in_array(strtolower($extention), $allowedExts)) { echo '<script type="text/javascript"> alert("Error uploading file: ' . $extention . '") </script>'; } else { // 预处理语句避免SQL注入 $sql = "SELECT NASLOV FROM Torrenti WHERE NASLOV = ?"; $stmt = mysqli_prepare($link, $sql); mysqli_stmt_bind_param($stmt, "s", $naslov); mysqli_stmt_execute($stmt); mysqli_stmt_store_result($stmt); $st_vrstic = mysqli_stmt_num_rows($stmt); mysqli_stmt_close($stmt); if ($st_vrstic == 1) { echo '<script type="text/javascript"> alert("Torrent already exists!") </script>'; } else { $torrentDatoteka = str_replace(' ', '_', $filename); $file123 = "files/" . $torrentDatoteka; $fileFullPath = "/var/www/html/torrent-tracker/files/" . $torrentDatoteka; if (file_exists($fileFullPath)) { echo '<script type="text/javascript"> alert("File already exists!") </script>'; } else { $username = $_SESSION['uporabnik']; // 预处理语句获取用户ID $sql = "SELECT ID FROM Blinker_IP WHERE UPORABNIK=?"; $stmt = mysqli_prepare($link, $sql); mysqli_stmt_bind_param($stmt, "s", $username); mysqli_stmt_execute($stmt); $vrstica = mysqli_fetch_row($stmt); $id_uporabnika = $vrstica[0]; mysqli_stmt_close($stmt); $path = "/var/www/html/torrent-tracker/files"; $tmp_name = $file['tmp_name']; $name = basename($torrentDatoteka); $sqlID = "SELECT MAX(ID) FROM Torrenti"; $rezultat = mysqli_query($link, $sqlID); $vrstica = mysqli_fetch_row($rezultat); $IdNovegaTorrenta = $vrstica[0] + 1; $vsebinaPoti = "VsebineTorrentov/" . $IdNovegaTorrenta . ".txt"; file_put_contents($vsebinaPoti, $_POST['vsebina']); if (move_uploaded_file($tmp_name, "$path/$name")) { echo "File moved successfully"; } else { echo "File move failed: " . error_get_last()["message"] . "<br>"; } // 预处理语句插入数据 $sql = "INSERT INTO Torrenti (NASLOV, VSEBINA, ID_UP, DATOTEKA, KATEGORIJA, ŽANR) VALUES (?, ?, ?, ?, ?, ?)"; $stmt = mysqli_prepare($link, $sql); mysqli_stmt_bind_param($stmt, "ssisss", $naslov, $vsebinaPoti, $id_uporabnika, $file123, $kategorija, $vseKategorije); mysqli_stmt_execute($stmt); mysqli_stmt_close($stmt); $location = (vrniRang() == 1) ? "index.php?stran=admin_main" : "index.php?stran=mod_main"; mysqli_close($link); header("Location: " . $location); exit; } } } } } }
3. 其他关键修复点
- SQL注入防护:原代码直接拼接用户输入到SQL语句,存在严重安全风险,修改后使用mysqli预处理语句绑定参数,彻底避免注入问题。
- 扩展名检查优化:用
in_array+strtolower统一扩展名大小写,避免因大小写差异导致的上传拒绝。 - 资源泄漏修复:在函数终止前关闭数据库连接,避免资源浪费。
- 逻辑简化:移除重复的
$st_vrstic == 0判断,精简代码流程。 - 表单验证:确保HTML表单添加
enctype="multipart/form-data"属性,否则文件无法正常上传。
内容的提问来源于stack exchange,提问作者Blinker
相关产品推荐
相关产品推荐

