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

PHP脚本可下载PDF,但无法正常下载根目录外的图片文件

PHP图片下载损坏问题排查与解决

问题现象

  • 从根目录外的uploads文件夹下载PNG/JPG图片时文件损坏,无法正常打开,但PDF文件可正常下载
  • 已确认:文件存在、MIME类型正确(image/png/image/jpeg)、文件非空,服务器本地可正常预览图片
  • 触发逻辑:前端点击后通过新窗口打开带GET参数的PHP页面,由前端控制器分发到视图处理

相关代码

前端触发代码

container.addEventListener('click', () => {
    // ... 获取用户ID和文件名 ...
    const open = `/view/?user=${user}&file=${file}&open=true`;
    window.open(open, '_blank');
});

视图处理代码

// 确保用户已认证...
if(isset($_GET['open']) && isset($_GET['user']) && isset($_GET['file'])){
    if(!Files::open($_GET['file'], $_GET['user'])){
        Report::error("Error");
    }
    Report::success("Success");
    exit();
}

文件处理核心函数Files::open()

/**
 * 打开请求的文件。
 * 
 * @param string $file 要打开的文件
 * @param string $folder 文件所在的文件夹
 * @return bool 文件成功打开则返回true,否则返回false
 */
public static function open(string $file, string $folder = ''): bool {
    // 路径遍历防护
    $file = str_replace(['../', '..\\'], '', $file);
    $path = dirname(__DIR__, 2) . "/uploads/$folder/$file";
    Report::notice("正在打开'$folder'文件夹中的文件'$file'。");

    if (!file_exists($path)) {
        Report::warning("'$folder'文件夹中不存在文件'$file'。");
        return false;
    }

    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $mime = $finfo->file($path);
    Report::notice("文件'$file'的MIME类型为'$mime'。");

    header("Content-Type: $mime");
    header("Content-Disposition: attachment; filename=$file");
    header("Content-Length: " . filesize($path));

    readfile($path);
    return true;
}

2023.05.16 更新:问题定位

下载的文件存在前置空白字符,PDF格式对这类冗余内容容错性高,而图片格式严格依赖文件头结构,因此出现损坏。


解决方案

1. 清理输出缓冲区

在输出文件内容前,清空所有缓冲的冗余内容:

// 在Files::open()函数设置HTTP头之前添加
ob_clean();
flush();

2. 禁止日志输出到响应流

Report::notice()/Report::error()等日志函数如果直接输出到浏览器,会导致空白/日志字符混入文件内容。必须将日志写入服务器本地文件(如用error_log()替代),而非HTTP响应流。

3. 移除多余的输出语句

视图文件中Report::success("Success");会在文件内容后添加额外字符,需删除该语句,直接在Files::open()处理完成后退出:

// 优化后的视图代码
if(isset($_GET['open']) && isset($_GET['user']) && isset($_GET['file'])){
    if(!Files::open($_GET['file'], $_GET['user'])){
        header("HTTP/1.1 404 Not Found");
        echo "文件不存在或无权访问";
    }
    exit();
}

4. 修复HTTP头的文件名编码

文件名含特殊字符时会导致头解析异常,需用rawurlencode()处理:

header("Content-Disposition: attachment; filename=\"" . rawurlencode($file) . "\"");

5. 检查所有PHP文件的首尾空白

确保所有被包含的PHP文件(包括类文件、控制器、视图)开头无多余空格/换行,结尾的?>可直接删除(避免意外输出空白)。


内容的提问来源于stack exchange,提问作者Ere Männistö

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 10:47:38