Laravel如何将控制器读取的PDF传入JS变量实现定时轮播展示
实现方案
核心原理
PDF是二进制文件,无法直接赋值给JS变量,需要先转为可被JS识别的文本格式,通常有两种实现方案:小体积PDF用Base64 Data URI传递,大体积PDF用独立路由返回文件流。
方案1:Base64传递(适合10M以内的小PDF)
第一步:修改控制器,转码后传递到视图
public function getPDFDocs() { $firstFileUrl = $secondFileUrl = ''; $disk = Storage::disk('test_docs'); if($disk->exists('testFirstFile.pdf')){ $file1 = $disk->get('testFirstFile.pdf'); // 转成PDF格式的Base64 Data URI $firstFileUrl = 'data:application/pdf;base64,' . base64_encode($file1); } if($disk->exists('testSecondFile.pdf')){ $file2 = $disk->get('testSecondFile.pdf'); $secondFileUrl = 'data:application/pdf;base64,' . base64_encode($file2); } return view('test.index') ->with('firstFile', $firstFileUrl) ->with('secondFile', $secondFileUrl); }
第二步:Blade模板实现渲染+轮播逻辑
先在页面HTML部分添加PDF展示容器:
<div class="pdf-container"> <!-- 也可替换为iframe标签兼容低版本浏览器,使用逻辑完全一致 --> <embed id="pdfViewer" width="100%" height="800px" type="application/pdf"> </div>
修改JS逻辑块:
@section('loadjs') function getPDFPages() { // 用Laravel自带的@json指令安全传递变量到JS,避免引号、转义问题 const pdfList = [ @json($firstFile), @json($secondFile) ]; const pdfViewer = document.getElementById('pdfViewer'); // 页面加载先展示第一份 if (pdfList[0]) pdfViewer.src = pdfList[0]; // 60秒后切换第二份 setTimeout(() => { if (pdfList[1]) pdfViewer.src = pdfList[1]; // 如需循环轮播,可在此处新增定时器切换数组下标即可 }, 60 * 1000); } // 页面加载完成后执行 window.addEventListener('load', getPDFPages); @endsection
方案2:路由返回文件流(适合大体积PDF,性能更好)
如果PDF体积较大,Base64编码会增大约33%的体积导致页面加载变慢,可以单独新增路由返回PDF响应,前端直接存储路由地址即可,性能更优。
第一步:新增路由
// routes/web.php Route::get('/pdf/{filename}', function ($filename) { $disk = Storage::disk('test_docs'); // 文件名白名单校验,避免路径遍历安全问题 $allowFiles = ['testFirstFile.pdf', 'testSecondFile.pdf']; if (!in_array($filename, $allowFiles) || !$disk->exists($filename)) { abort(404); } return response()->streamDownload(function () use ($disk, $filename) { echo $disk->get($filename); }, $filename, [ 'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline' // 配置为直接在浏览器展示,不触发下载 ]); })->name('pdf.show');
第二步:控制器传递路由地址到视图
public function getPDFDocs() { return view('test.index') ->with('firstFile', route('pdf.show', ['filename' => 'testFirstFile.pdf'])) ->with('secondFile', route('pdf.show', ['filename' => 'testSecondFile.pdf'])); }
前端HTML、JS逻辑和方案1完全一致,无需修改。
内容的提问来源于stack exchange,提问作者Geoff_S
相关产品推荐
相关产品推荐

