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

使用PDO从MSSQL读取二进制数据无法显示PDF/图片的问题

问题排查与解决步骤

1. 先解决输出污染问题

乱码/异常内容最常见的原因是输出响应头之前有隐性内容,比如PHP文件开头的BOM、空格,或者之前代码残留的echo/var_dump输出。这些内容会混入PDF数据流,导致浏览器无法解析:

  • 检查所有关联PHP文件,确保编码为UTF-8无BOM
  • 在header()调用前添加缓冲区清理代码,避免残留输出:
    ob_clean();
    flush();
    

2. 修正MSSQL LOB读取逻辑

MSSQL的PDO驱动处理LOB时,需要注意流指针的位置和读取时机,以下是修正后的完整代码:

<?php
// 清空输出缓冲区,确保header能正常发送
ob_clean();
flush();

$stmt = $pdo->prepare($sql);
$stmt->execute([$id]);

// 确认查询返回有效行
if ($stmt->rowCount() === 0) {
    die("附件不存在");
}

// 绑定列时注意:PDO bindColumn的索引从1开始计数,确认第10列确实是LOB字段
$stmt->bindColumn(10, $lob, PDO::PARAM_LOB);
$stmt->bindColumn(11, $attachment, PDO::PARAM_STR, 256); 

// 绑定后获取数据
$stmt->fetch(PDO::FETCH_BOUND);

// 重置流指针到起始位置,避免读取到空内容
rewind($lob);

// 根据扩展名设置正确的Content-Type
$ext = strtolower(substr(strrchr($attachment, '.'), 1));
$contentType = match($ext) {
    'pdf' => 'application/pdf',
    'jpg', 'jpeg' => 'image/jpeg',
    'png' => 'image/png',
    default => 'application/octet-stream'
};

// 设置完整响应头
header("Content-Type: $contentType");
header("Content-Disposition: inline; filename=\"$attachment\""); // inline表示浏览器直接打开,改为attachment则触发下载
header("Content-Length: " . stream_get_size($lob)); // 告诉浏览器文件大小,提升解析稳定性

// 输出LOB内容
fpassthru($lob);
exit; // 输出后立即终止脚本,避免后续代码产生额外输出

3. 优化PDO连接配置

给MSSQL的PDO连接添加必要属性,优化LOB读取兼容性:

$pdo = new PDO("sqlsrv:Server=你的服务器;Database=你的库", "账号", "密码", [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE => true,
    PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8
]);

4. 验证LOB数据本身完整性

如果以上步骤仍无效,先把LOB内容写入本地文件,确认数据库中的数据是否损坏:

file_put_contents('本地测试文件.pdf', stream_get_contents($lob));

打开生成的本地文件,若文件无法正常打开,说明数据库中存储的附件本身已损坏。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 13:36:12