You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过AJAX请求使用PHP存储上传的图片

问题:使用FormData+AJAX上传图片到PHP后端,move_uploaded_file无法存储文件

我正在结合FormData、JS和AJAX将文件发送到服务器,但在存储文件时遇到问题。move_uploaded_file()处理数组时直接失败,尝试使用文件名时无报错但仍无法成功存储文件。

AJAX请求代码

let fd = new FormData();
fd.append('id', id);
fd.append('name', name);
fd.append('caption', caption);

if( upload.cachedFileArray[0] !== null || typeof upload.cachedFileArray !== "undefined"){
    alert('defined...');
    alert(upload.cachedFileArray[0]);
    fd.append('file', upload.cachedFileArray[0]);
} else {
    alert(upload.cachedFileArray[0]);
    alert('U heeft nog geen afbeelding toegevoegd!');
}

$.ajax({
    url: '/SaveSlide',
    type: 'POST',
    processData: false,
    contentType: false,
    beforeSend: function (xhr) {
        const token = jQuery('meta[name="csrf_token"]').attr('content');
        if (token) {
            return xhr.setRequestHeader('X-CSRF-TOKEN', token);
        }
    },
    data: fd,
    success: function (data) {
        alert(data);
    }
});

PHP代码(原始错误版本)

public function SaveSlide(){
    if($_FILES['file']){
        //echo json_encode($_POST['id'] . $_POST ['name'] .$_POST['caption'] . var_dump($_FILES ['file']));
        if($_FILES['file']['type'] === "image/jpeg") {
            if (move_uploaded_file($_FILES['file'], asset('assets/img/'))) {
                echo json_encode('Uploaded!');
            } else {
                echo json_encode('Not uploaded :(!');
            }
        }
        //$html = $this->slideController->EditSlide($data);
    }
}

AJAX请求确实已将数据发送到服务器,我可以回显$_FILES['file']数组并查看,其结构如下:

name: "example.jpg"
lastmodified: 1620000000
lastmodifieddate: ...
WebkitRelativePath: ""
size: 123456
type: "image/jpeg"
slice: function(){}

请问如何将上传的图片成功存储到服务器?


解决方案

你的PHP代码里有两个核心错误导致move_uploaded_file执行失败,下面逐一修正并说明:

1. 修正move_uploaded_file的第一个参数

move_uploaded_file要求第一个参数是服务器临时文件的路径,也就是$_FILES['file']['tmp_name'],而不是整个$_FILES['file']数组。PHP接收上传文件时,会先把文件存到服务器临时目录,你需要从这个临时路径将文件移动到目标目录。

2. 修正目标路径

asset('assets/img/')是Laravel生成前端访问URL的辅助函数,输出的是类似http://yourdomain.com/assets/img/的网络地址,但move_uploaded_file需要的是服务器本地的文件系统绝对路径(比如/var/www/html/public/assets/img/)。

在Laravel中,你可以用public_path()获取public目录的绝对路径,再拼接上目标文件名(建议生成唯一文件名避免覆盖已有文件)。

修正后的PHP代码

public function SaveSlide(){
    // 先确认文件是否真的上传成功
    if(isset($_FILES['file']) && is_uploaded_file($_FILES['file']['tmp_name'])){
        $file = $_FILES['file'];
        
        // 放宽验证类型,同时后续可以补充更严谨的文件校验
        if(in_array($file['type'], ["image/jpeg", "image/png", "image/gif"])) {
            // 定义目标目录的绝对路径
            $targetDir = public_path('assets/img/');
            // 确保目录存在,不存在则递归创建
            if(!file_exists($targetDir)){
                mkdir($targetDir, 0755, true);
            }
            
            // 生成唯一文件名,避免同名文件覆盖
            $fileName = uniqid('slide_') . '_' . $file['name'];
            $targetPath = $targetDir . $fileName;
            
            // 执行文件移动操作
            if (move_uploaded_file($file['tmp_name'], $targetPath)) {
                // 返回前端可访问的文件URL,方便后续使用
                $fileUrl = asset('assets/img/' . $fileName);
                echo json_encode(['status' => 'success', 'message' => 'Uploaded!', 'file_url' => $fileUrl]);
            } else {
                echo json_encode(['status' => 'error', 'message' => 'Not uploaded :(!']);
            }
        } else {
            echo json_encode(['status' => 'error', 'message' => 'Only JPG/PNG/GIF files allowed!']);
        }
    } else {
        echo json_encode(['status' => 'error', 'message' => 'No file uploaded or upload failed!']);
    }
}

额外注意事项

  • 目录权限:确保public/assets/img/目录有服务器写入权限(通常设置为0755),否则move_uploaded_file会因权限不足失败。
  • 文件安全验证:仅靠type字段验证不够安全,建议同时验证文件扩展名,并用finfo函数检查文件真实类型,防止恶意文件上传。
  • 文件名处理:使用uniqid()生成唯一前缀可以有效避免同名文件覆盖,也可以根据业务需求自定义命名规则。

内容的提问来源于stack exchange,提问作者Rick J

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:24:09