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

如何在PHP Laravel中实现带缩略图的PDF查看器并替换图片展示

嘿,我来帮你搞定Laravel里替换图片展示为PDF展示,同时实现带缩略图的PDF查看器的需求!下面分步骤给你拆解解决方案:

1. 修改现有视图代码,替换图片展示为PDF预览

先把你当前的视图逻辑调整成适配PDF的版本,我们会替换原来的图片判断,改成显示PDF缩略图+查看/下载按钮:

<div class="row">
    <?php foreach ($rowData as $key => $row) { ?>
        <div class="col-md-3">
            <div class="card" style="width: 15rem;">
                <?php 
                $filename = $row->file;
                $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
                
                // 处理PDF文件
                if ($ext === 'pdf') {
                    // 缩略图存储路径:storage/app/public/pdf_thumbnails/[文件名].png
                    $thumbnailBaseName = pathinfo($filename, PATHINFO_FILENAME) . '.png';
                    $thumbnailStoragePath = "public/pdf_thumbnails/{$thumbnailBaseName}";
                    
                    // 判断缩略图是否存在,不存在则用默认占位图
                    if (Storage::exists($thumbnailStoragePath)) {
                        $thumbnailUrl = asset("storage/pdf_thumbnails/{$thumbnailBaseName}");
                    } else {
                        $thumbnailUrl = asset('images/default-pdf-thumbnail.png'); // 提前准备一个默认PDF缩略图
                    }
                ?>
                    <!-- 点击缩略图打开在线查看器 -->
                    <a href="{{ route('pdf.view', ['file' => $filename]) }}" target="_blank">
                        <img src="{{ $thumbnailUrl }}" class="card-img-top" alt="PDF 缩略图">
                    </a>
                <?php } else {
                    // 保留原有图片展示逻辑(如果还有非PDF文件需要处理)
                    $allowedImages = ['png', 'jpg', 'jpeg'];
                    if (in_array($ext, $allowedImages)) {
                        $fileUrl = asset("storage/{$filename}");
                ?>
                        <img src="{{ $fileUrl }}" class="card-img-top" alt="图片预览">
                <?php }
                } ?>
                <div class="card-body">
                    <h5 class="card-title">{{ $row->title ?? '未命名文件' }}</h5>
                    <!-- 下载按钮 -->
                    <a href="{{ asset("storage/{$filename}") }}" class="btn btn-primary" download>下载文件</a>
                    <!-- 在线查看按钮 -->
                    <a href="{{ route('pdf.view', ['file' => $filename]) }}" class="btn btn-secondary" target="_blank">在线查看</a>
                </div>
            </div>
        </div>
    <?php } ?>
</div>
2. 生成PDF缩略图(Laravel实现)

要生成PDF的第一页作为缩略图,推荐用Spatie的pdf-to-image包(封装了Imagick,简化开发),或者手动用Imagick实现:

方法A:用Spatie的PDF转图片包

  1. 先安装包:
composer require spatie/pdf-to-image
  1. 服务器依赖:确保服务器安装了Imagick和Ghostscript(Ubuntu可以用sudo apt install ghostscript php-imagick安装,CentOS用yum install ghostscript php-pecl-imagick)。
  2. 在文件上传逻辑中添加缩略图生成代码:
use Spatie\PdfToImage\Pdf;
use Illuminate\Support\Facades\Storage;

public function uploadPdf(Request $request)
{
    // 验证上传文件
    $request->validate([
        'pdf_file' => 'required|mimes:pdf|max:10240', // 限制10MB以内
    ]);

    // 存储PDF到storage/app/public/pdfs目录
    $pdfFile = $request->file('pdf_file');
    $storedPath = $pdfFile->store('pdfs', 'public');
    $pdfStoragePath = storage_path("app/public/{$storedPath}");

    // 生成第一页缩略图,保存到pdf_thumbnails目录
    $thumbnailDir = storage_path('app/public/pdf_thumbnails');
    if (!file_exists($thumbnailDir)) {
        mkdir($thumbnailDir, 0755, true);
    }

    $thumbnailPath = "{$thumbnailDir}/" . pathinfo($storedPath, PATHINFO_FILENAME) . '.png';
    $pdf = new Pdf($pdfStoragePath);
    $pdf->setOutputFormat('png')
        ->setPage(1) // 只取第一页
        ->setResolution(150) // 设置分辨率,提高清晰度
        ->saveImage($thumbnailPath);

    // 这里可以把$storedPath保存到数据库,关联到你的数据模型
    return redirect()->back()->with('success', 'PDF上传并生成缩略图成功!');
}
  1. 最后运行php artisan storage:link,把storage的public目录链接到项目的public目录,确保前端能访问到文件。

方法B:手动用Imagick实现(无需第三方包)

如果不想用第三方包,可以直接用PHP的Imagick扩展:

$imagick = new \Imagick();
$imagick->setResolution(150, 150); // 设置分辨率
$imagick->readImage($pdfStoragePath . '[0]'); // 读取PDF第一页([0]代表第一页)
$imagick->setImageFormat('png');
$imagick->resizeImage(300, 0, \Imagick::FILTER_LANCZOS, 1); // 按宽度300px缩放,高度自适应
$imagick->writeImage($thumbnailPath);
$imagick->clear();
$imagick->destroy();
3. 创建带功能的PDF在线查看器

有两种实现方式,按需选择:

方式1:原生浏览器嵌入(简单快速)

直接用浏览器的原生PDF查看器,不需要额外依赖:

  1. 先添加路由(routes/web.php):
use Illuminate\Support\Facades\Storage;

Route::get('/pdf/view/{file}', function ($file) {
    // 验证文件是否存在
    $pdfStoragePath = "public/pdfs/{$file}";
    if (!Storage::exists($pdfStoragePath)) {
        abort(404, 'PDF文件不存在');
    }

    $pdfUrl = asset("storage/pdfs/{$file}");
    return view('pdf.view', compact('pdfUrl'));
})->name('pdf.view');
  1. 创建查看器视图(resources/views/pdf/view.blade.php):
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>PDF在线查看</title>
    <style>
        body {
            margin: 20px;
            padding: 0;
        }
        .pdf-container {
            width: 100%;
            height: 90vh;
            border: 1px solid #e0e0e0;
            border-radius: 4px;
        }
        .action-buttons {
            margin-top: 15px;
        }
    </style>
</head>
<body>
    <h2>PDF在线查看</h2>
    <div class="pdf-container">
        <embed src="{{ $pdfUrl }}" type="application/pdf" width="100%" height="100%">
    </div>
    <div class="action-buttons">
        <a href="{{ $pdfUrl }}" download class="btn btn-primary">下载PDF</a>
        <a href="{{ url()->previous() }}" class="btn btn-secondary">返回文件列表</a>
    </div>
</body>
</html>

方式2:用PDF.js实现功能丰富的查看器

如果需要缩放、搜索、页码跳转等高级功能,推荐用Mozilla的PDF.js库:

  1. 下载PDF.js:从官网下载最新包,把里面的web目录复制到你的项目public/pdfjs目录下。
  2. 修改查看器视图:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>PDF高级查看器</title>
    <style>
        body, html {
            margin: 0;
            padding: 0;
            height: 100%;
        }
        iframe {
            width: 100%;
            height: 100%;
            border: none;
        }
    </style>
</head>
<body>
    <!-- 嵌入PDF.js的查看器页面,传递PDF文件的URL -->
    <iframe src="{{ asset('pdfjs/web/viewer.html?file=' . urlencode($pdfUrl)) }}"></iframe>
</body>
</html>
注意事项
  • 确保storage/app/public/pdfs和storage/app/public/pdf_thumbnails目录有写权限(可以用chmod -R 755 storage/设置)。
  • 如果服务器没有Imagick/Ghostscript,也可以考虑在上传时调用第三方API生成缩略图,但性能和稳定性不如本地生成。
  • 可以给缩略图添加懒加载,优化页面加载速度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:32:07