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 的场景:
- 文件存放在非公开目录,必须通过 Laravel 读取并返回;
- 需要添加权限校验、预览次数统计、日志记录等额外业务逻辑;
- 需对文件做格式转换(如 XLS 转 HTML)。
内容的提问来源于stack exchange,提问作者helloimriz
相关产品推荐
相关产品推荐

