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

PHP REST API文件上传下载功能.sql文件下载后大小为0或损坏问题

修复方案

核心问题根因

你遇到的下载文件异常是以下几个问题共同导致的:

  • 错误使用HTTP协议读取本地文件,且未对文件名做URL编码:你构造的请求URL中包含带空格的文件名mtc_project (1).sql,空格属于URL非法字符,未编码就发起请求会被服务器判定为非法请求返回400错误,readfile读取失败所以输出内容为空/仅包含PHP警告,最终下载的文件大小异常、无法打开。
  • 多余的HTTP请求开销+稳定性问题:需要读取的文件本身就在服务器本地磁盘,完全不需要绕一圈走HTTP请求,直接读文件系统路径既可以避免URL编码类问题,性能也更高。
  • exit位置错误:readfile执行后直接调用exit,后续的下载状态更新SQL永远不会被执行。
  • 额外风险:你原有SQL直接拼接参数$param,存在SQL注入漏洞;直接使用用户上传的原始文件名存储,存在路径遍历、特殊字符兼容问题。

修复后代码

下载函数修复

public function downloadFile($param){
    // 和上传逻辑保持一致的本地文件存储路径
    $file_path_prefix = '../files/';
 
    // 改为参数绑定,避免SQL注入
    $q = "SELECT * FROM data_file WHERE module_id = ?";
    $stmt = $this->conn->prepare($q);
    $stmt->execute([$param]);

    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    
    if(!empty($row)){
        $filename = $row['file_name'];
        $full_file_path = $file_path_prefix . $filename;
        // 提前判断本地文件是否存在、可读
        if(!file_exists($full_file_path) || !is_readable($full_file_path)){
            Responses::http_not_found();
            exit();
        }
        // 输出下载头
        header('Content-Type: application/octet-stream');
        header("Content-Transfer-Encoding: Binary"); 
        header("Content-disposition: attachment; filename=\"". $filename . "\""); 
        // 直接读本地文件输出
        readfile($full_file_path); 

        // 把状态更新逻辑放到exit之前执行
        $date = date('Y-m-d H:i:s');
        $update = "UPDATE server_status SET file_start = ?, file_start_time = ? WHERE module_id = ?";
        $updateStmnt2 = $this->conn->prepare($update);
        $updateStmnt2->execute([
            2,
            $date,
            $param
        ]);
        exit();
    }else{
        Responses::http_not_found();
    }
}

上传函数优化(可选,彻底解决文件名兼容问题)

public function uploadFile($param,$file){
    $upload_path = '../files/';
    $temp_path = $file['tmp_name'];
    // 替换文件名中的空格、特殊字符,避免后续读取兼容问题
    $safe_filename = preg_replace('/[^\w\.\-]/u', '_', $file['name']);
    // 也可以选择重命名文件彻底避免重名、特殊字符问题:
    // $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
    // $safe_filename = time() . '_' . uniqid() . '.' . $ext;
    
    if (file_exists($upload_path . $safe_filename)) {
        unlink($upload_path . $safe_filename);
    }

    if(move_uploaded_file($temp_path,$upload_path.$safe_filename)){
        // 存储处理后的安全文件名到数据库
        $file['name'] = $safe_filename;
        $this->setFileQuery($param,$file);
    }else{
        Responses::http_error();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 22:15:06