动态加载 Laravel 项目中存储目录下的图片资源

2次阅读

动态加载 Laravel 项目中存储目录下的图片资源

本文详解如何在 laravel Blade 模板中通过纯 JavaScript 动态加载 storage/app/public/designImages/ 目录下的 PNG 图片,解决因混合使用 Blade 指令与 js 变量导致的路径解析失败和 404 错误问题。

本文详解如何在 laravel blade 模板中通过纯 javascript 动态加载 `storage/app/public/designimages/` 目录下的 png 图片,解决因混合使用 blade 指令与 js 变量导致的路径解析失败和 404 错误问题。

在 Laravel 中实现图片资源的动态展示,关键在于分离服务端路径解析与客户端运行时逻辑。你最初尝试在 JavaScript 中直接嵌入 Blade 指令 {{ asset(‘designImages/design-${i}.png’) }} 是无效的——因为 Blade 模板引擎在服务器端完成渲染后即退出,此时 JS 代码尚未执行,且 ${i} 是 es6 模板字符串语法,而 Blade 的 {{ }} 在 HTML 输出阶段已被静态编译为固定路径(例如 {{ asset(‘designImages/design-${i}.png’) }} 实际会被解析为字面量 designImages/design-${i}.png,而非动态拼接),最终导致浏览器请求形如 /designImages/design-${i}.png 的非法 URL,返回 404。

✅ 正确方案:完全由前端控制路径生成,并确保该路径可被 Web 服务器公开访问

✅ 前提:正确配置 Laravel 存储链接

Laravel 默认将用户上传或需公开访问的文件存于 storage/app/public/。要使 designImages/ 文件夹可通过 http 访问,必须先创建符号链接:

php artisan storage:link

执行后,public/storage/ 将指向 storage/app/public/。因此,存放图片的实际路径应为:

storage/app/public/designImages/design-1.png storage/app/public/designImages/design-2.png ...

对应可公开访问的 URL 路径即为:

/storage/designImages/design-1.png

⚠️ 注意:/storage/ 是 Laravel 约定的公开存储挂载路径,不可写作 /designImages/ 或 /public/designImages/ —— 后者在默认配置下不被路由支持,必然 404。

✅ JavaScript 动态生成图片路径(推荐写法)

将以下代码保存为 public/js/imageGrid.js(确保已通过 @push(‘head’) 正确引入):

document.addEventListener('DOMContentLoaded', () => {     const imageContainer = document.querySelector('.imageContainer');     const baseUri = '/storage/designImages/design-'; // 统一前缀,结尾不带扩展名     const totalImages = 13; // 根据实际数量调整(i 从 1 到 13 → 共 13 张)      for (let i = 1; i <= totalImages; i++) {         const img = document.createElement('img');         img.src = `${baseUri}${i}.png`;         img.alt = `Design project #${i}`;         img.loading = 'lazy'; // 提升性能         img.className = 'design-thumbnail'; // 可选:便于 CSS 控制样式          // 添加错误兜底处理(防止单张图损坏影响整体)         img.onerror = function() {             this.style.display = 'none';             console.warn(`Failed to load image: ${this.src}`);         };          imageContainer.appendChild(img);     } });

✅ Blade 模板保持简洁(无需修改)

index.blade.php 中维持原结构即可:

@section('content-5')     <div class="imageContainer">         <!-- images will be injected here by JS -->     </div> @endsection  @push('head')     <script src="{{ asset('js/imageGrid.js') }}"></script> @endpush

✅ 优势说明:

  • 完全避免 Blade 与 JS 的上下文混淆;
  • 路径由前端拼接,灵活可控(如后续改为 .jpg 或增加前缀,仅改 JS 即可);
  • 支持懒加载、错误降级、语义化属性(alt, loading),符合现代 Web 最佳实践。

? 调试建议

  • 打开浏览器开发者工具 → Network 标签页,筛选 Img 类型,观察请求 URL 是否为 /storage/designImages/design-1.png
  • 确保该 URL 在浏览器中可直接访问(例如手动输入 https://mywebsite.test/storage/designImages/design-1.png);
  • 若仍 404,请检查:
    • storage/app/public/designImages/ 目录是否存在且权限正确(Web 服务器可读);
    • php artisan storage:link 是否成功执行(检查 public/storage 是否为有效软链);
    • apache/nginx 是否启用 FollowSymLinks(Apache)或正确配置 alias(Nginx)。

✅ 进阶提示(可选)

若未来图片数量不确定,可考虑通过 Laravel API 返回文件列表(如 GET /api/design-images),再由 JS 动态渲染,彻底解耦路径维护逻辑。但对于静态作品集场景,上述纯前端方案已足够轻量、可靠且易于维护。

至此,你的作品集图片即可真正“动态就绪”:新增一张 design-14.png,只需更新 JS 中 totalImages = 14,刷新页面即生效——无需修改 Blade、不重启服务、不重新部署。

text=ZqhQzanResources