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

Laravel中如何实现jpg、xls、pdf预览?是否需创建controller?

Laravel 实现 JPG、XLS、PDF 文件预览方案

一、JPG 图片预览

直接使用 <img> 标签即可,前提是图片存放在可公开访问的目录(如 storage/app/public,需先执行 php artisan storage:link 创建软链接):

<!-- 直接指定公开路径 -->
<img src="{{ asset('storage/images/demo.jpg') }}" alt="图片预览">

<!-- 从模型获取存储路径 -->
<img src="{{ Storage::url($post->image_path) }}" alt="图片预览">

这种场景下无需额外创建 Controller,浏览器可直接访问图片文件。

二、PDF 文件预览

方式1:浏览器原生预览(无需 Controller)

如果 PDF 存放在公开目录,直接用 <a> 标签打开新标签页,浏览器会自动渲染预览:

<a href="{{ asset('storage/docs/demo.pdf') }}" target="_blank">预览 PDF</a>

也可以用 <iframe> 嵌入页面内预览:

<iframe src="{{ asset('storage/docs/demo.pdf') }}" width="100%" height="600px"></iframe>

方式2:非公开文件预览(需 Controller)

若文件存放在非公开目录(如 storage/app/private),需通过 Controller 读取文件并返回响应,同时可添加权限校验:

// 新建 PreviewController.php
namespace App\Http\Controllers;

use Illuminate\Support\Facades\Response;

class PreviewController extends Controller
{
    public function pdf(string $filename)
    {
        $filePath = storage_path("app/private/{$filename}");
        
        if (!file_exists($filePath)) {
            abort(404);
        }

        // 返回文件并指定为在线预览(而非下载)
        return Response::file($filePath, [
            'Content-Type' => 'application/pdf',
            'Content-Disposition' => "inline; filename=\"{$filename}\""
        ]);
    }
}

配置路由:

// routes/web.php
Route::get('preview/pdf/{filename}', [\App\Http\Controllers\PreviewController::class, 'pdf']);

前端调用:

<a href="{{ route('preview.pdf', ['filename' => 'demo.pdf']) }}" target="_blank">预览私有 PDF</a>

三、XLS 文件预览

浏览器原生不支持 XLS 预览,需借助前端库或后端转换:

方式1:前端用 SheetJS 渲染

引入 SheetJS 库(CDN 方式),直接读取文件并生成 HTML 表格:

<input type="file" id="xlsInput">
<div id="xlsPreview"></div>

<script src="https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js"></script>
<script>
document.getElementById('xlsInput').addEventListener('change', (e) => {
    const file = e.target.files[0];
    const reader = new FileReader();
    
    reader.onload = (event) => {
        const data = new Uint8Array(event.target.result);
        const workbook = XLSX.read(data, { type: 'array' });
        const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
        // 将工作表转为 HTML
        document.getElementById('xlsPreview').innerHTML = XLSX.utils.sheet_to_html(firstSheet);
    };
    
    reader.readAsArrayBuffer(file);
});

如果是服务器上的私有 XLS 文件,同样需要通过 Controller 返回文件内容,再用前端读取渲染:

// PreviewController.php 新增方法
public function xls(string $filename)
{
    $filePath = storage_path("app/private/{$filename}");
    
    if (!file_exists($filePath)) {
        abort(404);
    }

    return Response::file($filePath, [
        'Content-Type' => 'application/vnd.ms-excel',
    ]);
}

前端通过 Fetch 请求:

fetch('/preview/xls/demo.xls')
.then(res => res.arrayBuffer())
.then(data => {
    const workbook = XLSX.read(data, { type: 'array' });
    const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
    document.getElementById('xlsPreview').innerHTML = XLSX.utils.sheet_to_html(firstSheet);
});

方式2:后端转换为 HTML(需依赖包)

安装 maatwebsite/excel 包,在后端将 XLS 转为 HTML 表格返回:

composer require maatwebsite/excel

Controller 方法:

use Maatwebsite\Excel\Facades\Excel;

public function xlsPreview(string $filename)
{
    $filePath = storage_path("app/private/{$filename}");
    $sheetData = Excel::toArray([], $filePath)[0];
    
    // 生成 HTML 表格
    $html = '<table border="1" cellpadding="8">';
    foreach ($sheetData as $row) {
        $html .= '<tr>';
        foreach ($row as $cell) {
            $html .= "<td>{$cell}</td>";
        }
        $html .= '</tr>';
    }
    $html .= '</table>';
    
    return $html;
}

四、是否需要创建 Controller?

  • 无需 Controller 的场景:文件存放在公开可访问目录(如 public/storage),直接用 <a>/<img>/<iframe> 访问即可,无需额外逻辑。
  • 需要 Controller 的场景:
    1. 文件存放在非公开目录,必须通过 Laravel 读取并返回;
    2. 需要添加权限校验、预览次数统计、日志记录等额外业务逻辑;
    3. 需对文件做格式转换(如 XLS 转 HTML)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 09:06:37