在 Laravel 中同时存储原始图片和 WebP 转换图片

在 Laravel 中同时存储原始图片和 WebP 转换图片

本文详细介绍了在 Laravel 应用中如何高效地处理图片上传,实现同时保存原始图片(如 JPG/PNG)及其 WebP 转换版本。通过利用 PHP 原生 GD 库功能,我们能够克服 Intervention Image 在特定场景下的路径写入问题,确保原始图片和优化后的 WebP 格式文件都能正确存储到指定路径,从而提升网站性能并保持原始图像数据。

引言

在现代 web 开发中,图片优化对于提升网站性能和用户体验至关重要。webp 格式因其卓越的压缩效率和无损/有损压缩能力而广受欢迎。然而,在某些场景下,我们可能需要同时保留用户上传的原始图片(例如用于未来编辑、打印或作为高质量备份),并生成一个 webp 优化版本供前端展示。本文将探讨如何在 laravel 项目中实现这一目标,特别是当使用 intervention image 库遇到写入路径问题时,如何采用 php 原生 gd 库功能进行有效处理。

常见问题分析

开发者在使用 Intervention Image 库尝试将转换后的 WebP 图片保存到 Laravel 存储时,可能会遇到类似 “Can’t write image data to path (public/images/newimage.jpg.webp)” 的错误。这通常是由于以下原因造成的:

路径混淆: Intervention Image 的 save() 方法可能期望一个文件系统路径,而不是 Laravel 的 Storage 门面所使用的抽象路径。直接拼接 public/images/ 字符串可能导致权限问题或路径解析错误,尤其是在 Laravel 应用程序中,public/ 目录通常通过 public_path() 或 Storage::disk(‘public’) 来访问。文件写入权限: 目标路径没有正确的写入权限。操作顺序: 在某些情况下,可能在原始图片尚未完全保存到目标位置之前就尝试读取或转换。

解决方案:利用 PHP 原生 GD 库进行 WebP 转换

当 Intervention Image 库在特定场景下遇到路径写入问题时,我们可以退而求其次,利用 PHP 内置的 GD 库功能进行 WebP 转换。这种方法提供了更底层的控制,并且在许多服务器环境中 GD 库都是默认开启的。

以下是一个在 Laravel 中实现同时保存原始图片和 WebP 转换版本的示例:

hasFile('fileName') || !$request->file('fileName')->isValid()) {            return response()->json(['error' => '未找到上传文件或文件无效'], 400);        }        $file = $request->file('fileName');        $allowedExtensions = ['jpg', 'jpeg', 'png'];        $extension = strtolower($file->getClientOriginalExtension());        if (!in_array($extension, $allowedExtensions)) {            return response()->json(['error' => '不支持的文件格式,只允许 JPG, JPEG, PNG'], 422);        }        // 2. 定义存储路径和文件名        // 建议使用 Storage 门面来管理文件存储,无论本地还是云存储        $disk = 'public'; // 使用 public 磁盘,实际路径为 storage/app/public        $folder = 'images/article-images';        $originalFileName = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);        $uniqueId = uniqid(); // 生成唯一ID,避免文件名冲突        $originalImageName = $originalFileName . '_' . $uniqueId . '.' . $extension;        $webpImageName = $originalFileName . '_' . $uniqueId . '.webp';        // 3. 保存原始图片到 Laravel 存储        // putFileAs 会自动生成一个唯一的哈希文件名,但我们这里想保留原始文件名的一部分        // 或者直接使用 putFileAs,然后记录其返回的路径        $originalPath = Storage::disk($disk)->putFileAs($folder, $file, $originalImageName);        if (!$originalPath) {            return response()->json(['error' => '无法保存原始图片'], 500);        }        // 4. 获取原始图片的完整文件系统路径,用于 GD 库处理        // 注意:Storage::path() 返回的是文件在服务器上的绝对路径        $fullOriginalImagePath = Storage::disk($disk)->path($originalPath);        // 5. 使用 GD 库创建图像资源        $image = null;        switch ($extension) {            case 'jpeg':            case 'jpg':                $image = imagecreatefromjpeg($fullOriginalImagePath);                break;            case 'png':                $image = imagecreatefrompng($fullOriginalImagePath);                // 对于 PNG,需要保留透明度                imagealphablending($image, false);                imagesavealpha($image, true);                break;            default:                // 理论上前面已经过滤了,这里作为保险                return response()->json(['error' => '不支持的图像格式进行 GD 处理'], 500);        }        if (!$image) {            return response()->json(['error' => '无法创建图像资源'], 500);        }        // 6. 转换为真彩色(如果不是)        // 某些调色板图像(如GIF)转换为WebP可能需要先转为真彩色        imagepalettetotruecolor($image);        // 7. 将图像资源保存为 WebP 格式到临时位置        $tempWebpPath = tempnam(sys_get_temp_dir(), 'webp_'); // 创建临时文件        if (!imagewebp($image, $tempWebpPath, 80)) { // 80 是 WebP 质量 (0-100)            imagedestroy($image);            @unlink($tempWebpPath); // 清理临时文件            return response()->json(['error' => '无法将图片转换为 WebP 格式'], 500);        }        // 8. 将 WebP 临时文件移动到 Laravel 存储        $webpStoragePath = $folder . '/' . $webpImageName;        $webpContent = file_get_contents($tempWebpPath);        if (!Storage::disk($disk)->put($webpStoragePath, $webpContent)) {            imagedestroy($image);            @unlink($tempWebpPath);            return response()->json(['error' => '无法保存 WebP 图片到存储'], 500);        }        // 清理 GD 资源和临时文件        imagedestroy($image);        @unlink($tempWebpPath);        // 9. 更新数据库(示例)        $imageModel = new Image();        $imageModel->title = $originalFileName;        $imageModel->original_path = $originalPath; // 存储原始图片路径        $imageModel->webp_path = $webpStoragePath;   // 存储 WebP 图片路径        $imageModel->description = $request->description;        $imageModel->author_id = $request->author_id;        $imageModel->save();        // 10. 关联文章(如果需要)        if ($request->article_id) {            // 假设 Image 模型与 Article 模型有多对多关系            $imageModel->articles()->attach($request->article_id);        }        return response()->json(['message' => '图片上传成功', 'image' => $imageModel], 201);    }}

代码解析:

文件验证: 确保上传的文件存在且是允许的图片格式(JPG, JPEG, PNG)。路径定义: 使用 Laravel 的 Storage 门面定义存储磁盘和文件夹。这里我们使用 public 磁盘,它对应 storage/app/public 目录,通常通过 php artisan storage:link 软链接到 public/storage 供 Web 访问。保存原始图片: Storage::disk($disk)->putFileAs($folder, $file, $originalImageName) 将原始文件保存到指定路径,并返回相对路径。获取完整路径: Storage::disk($disk)->path($originalPath) 用于获取服务器上原始图片的绝对文件系统路径,这是 GD 库函数所需要的。创建图像资源: 根据原始图片的扩展名,使用 imagecreatefromjpeg() 或 imagecreatefrompng() 创建 GD 图像资源。对于 PNG 格式,需要额外处理透明度。转换为真彩色: imagepalettetotruecolor() 是一个重要的步骤,它确保图像在转换为 WebP 时具有更准确的颜色表示,尤其对于某些调色板图像。保存为 WebP: imagewebp($image, $tempWebpPath, 80) 是核心步骤。它将 GD 图像资源 $image 转换为 WebP 格式,并保存到 $tempWebpPath 指定的临时文件。80 是 WebP 的质量参数,范围从 0(最差质量,最小文件)到 100(最佳质量,最大文件)。移动 WebP 文件: 由于 imagewebp 直接保存到文件系统,我们需要将这个临时 WebP 文件读取出来,然后通过 Storage::disk($disk)->put() 方法将其内容写入 Laravel 存储系统。清理: imagedestroy($image) 释放 GD 图像资源占用的内存,@unlink($tempWebpPath) 删除创建的临时 WebP 文件。数据库更新: 将原始图片和 WebP 图片的路径存储到数据库中,以便后续检索和使用。

注意事项和最佳实践

GD 库安装: 确保你的 PHP 环境已经安装并启用了 GD 库。可以通过 phpinfo() 检查。

文件权限: 确保 storage/app/public 目录及其子目录具有写入权限(通常是 chmod -R 775 storage)。

异步处理: 对于高并发或大尺寸图片的上传,图片转换是一个计算密集型操作。考虑使用 Laravel 队列(Queues)将图片转换任务推送到后台处理,以避免阻塞主请求。

错误处理: 在实际应用中,需要更全面的错误处理,例如捕获文件操作异常、GD 函数执行失败等。

图片尺寸调整: 如果需要对 WebP 图片进行尺寸调整,可以在 imagewebp 之前使用 GD 库的其他函数(如 imagescale() 或手动实现 imagecopyresampled())进行处理。

路径管理: 始终使用 Storage 门面来管理文件路径,这使得你的应用在切换存储驱动(如从本地到 AWS S3)时更加灵活。

数据库设计: 在 images 表中,可以为原始图片和 WebP 图片分别设置字段(如 original_path 和 webp_path),或者使用一个字段存储 JSON 格式的路径信息。

前端展示: 在前端,可以使用 标签结合 元素来优雅地提供 WebP 和原始图片作为回退,例如:

    webp_path }}" type="image/webp">    @@##@@original_path }}" alt="{{ $image->title }}">

总结

通过上述方法,我们可以在 Laravel 应用程序中有效地管理图片上传,同时保存原始图片和其 WebP 转换版本。这种策略不仅能满足不同场景下的图片需求,还能通过 WebP 格式显著优化网站的加载性能。虽然 Intervention Image 是一个功能强大的库,但在遇到特定路径写入问题时,灵活地切换到 PHP 原生 GD 库是一个可靠且有效的解决方案。记住,良好的错误处理、异步处理和正确的路径管理是构建健壮图片处理系统的关键。

” alt=”在 Laravel 中同时存储原始图片和 WebP 转换图片” >

以上就是在 Laravel 中同时存储原始图片和 WebP 转换图片的详细内容,更多请关注php中文网其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1322241.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
使用PHP正则表达式从字符串末尾提取数字的教程
上一篇 2025年12月12日 08:25:24
PHP 实现 JSON 数据按月统计:以 Start_Date 字段为例
下一篇 2025年12月12日 08:25:38

相关推荐

  • Laravel中collection类的使用方法总结(代码)

    Laravel中collection类的使用方法总结(代码)Laravel中collection类的使用方法总结(代码)Laravel中collection类的使用方法总结(代码)Laravel中collection类的使用方法总结(代码)

    Laravel 的 Collection 类其实有很多非常实用的方法,对于我们在优化循环的时候非常的有用,我们的目标就是:不再写 foreach 循环!这篇文章给大家分享的内容是关于Laravel中collection类的使用方法总结(代码),内容很详细,有一定的参考价值,希望可以帮助到有需要的朋友…

    2026年9月27日 • 用户投稿
    100
  • 有好看漫画合集的app推荐 推荐十个有好看漫画的软件大全

    有好看漫画合集的app推荐 推荐十个有好看漫画的软件大全有好看漫画合集的app推荐 推荐十个有好看漫画的软件大全有好看漫画合集的app推荐 推荐十个有好看漫画的软件大全有好看漫画合集的app推荐 推荐十个有好看漫画的软件大全

    为了帮助广大爱好者找到心仪的阅读平台,我们精心整理了十款备受好评的漫画软件。这些应用不仅拥有海量作品库,还在阅读体验和社区互动方面各具特色,让你轻松告别书荒。 小编推荐一、☞☞☞☞点击必备的看漫APP☜☜☜☜☜ 小编推荐二、☞☞☞☞点击漫画资源最全的平台入口☜☜☜☜☜ 一、快看 1、这是一款非常受年…

    2026年9月26日 • 用户投稿
    200
  • 如何正确配置防火墙规则以平衡安全与性能?

    如何正确配置防火墙规则以平衡安全与性能?如何正确配置防火墙规则以平衡安全与性能?如何正确配置防火墙规则以平衡安全与性能?如何正确配置防火墙规则以平衡安全与性能?

    答案是:防火墙规则需基于最小权限和默认拒绝原则,结合网络拓扑细化规则、定期审计清理僵尸规则,并利用日志监控优化性能与安全;在云环境则需借助自动化工具实现分布式、细粒度的动态防护。 配置防火墙规则以平衡安全与性能,这从来就不是一个一劳永逸的事情,它更像是一场持续的拉锯战。核心在于,你必须清楚地知道自己…

    2026年9月26日 • 用户投稿
    000
  • TikTok视频播放黑屏怎么办

    TikTok视频播放黑屏怎么办TikTok视频播放黑屏怎么办TikTok视频播放黑屏怎么办TikTok视频播放黑屏怎么办

    先检查网络连接,切换Wi-Fi与移动数据并重启路由器;再清理TikTok缓存,进入应用管理存储项点击清除缓存;接着更新或重装App;最后核对系统时间与权限设置,确保网络和存储权限开启。 遇到TikTok视频播放黑屏的问题,通常和网络、缓存或应用本身有关。别急,可以一步步排查解决。 检查网络连接 视频…

    2026年9月26日 • 用户投稿
    000
  • Laravel的功能测试:测试驱动开发(附代码)

    本篇文章给大家带来的内容是关于laravel的功能测试:测试驱动开发(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 创建carousel功能测试 在对你的项目进行功能测试的时候,一定要确保管理后台的功能测试要与前台的功能测试隔离开来。在本例中,我通过命名空间Admin和F…

    2026年9月26日
    200
  • TGS 2025:《雷顿教授与蒸汽新世界》延期到2026年发售

    TGS 2025:《雷顿教授与蒸汽新世界》延期到2026年发售TGS 2025:《雷顿教授与蒸汽新世界》延期到2026年发售TGS 2025:《雷顿教授与蒸汽新世界》延期到2026年发售TGS 2025:《雷顿教授与蒸汽新世界》延期到2026年发售

    在tgs 2025展会上,level 5正式宣布《雷顿教授与蒸气新世界》将延期至2026年推出。与此同时,游戏媒体巴哈姆特释出了一段长达12分钟的实机试玩影片,让玩家得以抢先了解当前版本的游戏内容与开发进度。 AI新媒体文章 专为新媒体人打造的AI写作工具,提供“选题创作”、“文章重写”、“爆款标题…

    2026年9月26日 • 用户投稿
    000
  • 京东商品没有客服是怎么回事?快递退货该如何报备?退货报备全流程解析

    京东商品没有客服是怎么回事?快递退货该如何报备?退货报备全流程解析京东商品没有客服是怎么回事?快递退货该如何报备?退货报备全流程解析京东商品没有客服是怎么回事?快递退货该如何报备?退货报备全流程解析京东商品没有客服是怎么回事?快递退货该如何报备?退货报备全流程解析

    在京东购物时,许多用户会发现某些商品页面缺少直接的客服联系入口,一旦遇到商品质量问题或需要售后服务,往往会产生焦虑情绪。此外,在退货过程中如何正确申报快递信息、避免售后纠纷,也成为消费者普遍关心的问题。本文将深入解读京东客服系统的运行逻辑,并详细演示退货报备的完整操作流程。 一、为何部分京东商品不显…

    2026年9月26日 • 用户投稿
    500
  • PHP中动态设置HTML 背景色的正确实践

    <img src="https://img.php.cn/upload/article/001/246/273/175965168921241.jpg" alt="php中动态设置html 背景色的正确实践”>背景色的正确实践” /&…

    用户投稿 2026年9月26日
    000
  • 京东双11 Plus会员优惠券怎么转赠_京东双11 Plus券转赠方法

    京东双11 Plus会员优惠券怎么转赠_京东双11 Plus券转赠方法京东双11 Plus会员优惠券怎么转赠_京东双11 Plus券转赠方法京东双11 Plus会员优惠券怎么转赠_京东双11 Plus券转赠方法京东双11 Plus会员优惠券怎么转赠_京东双11 Plus券转赠方法

    可通过京东APP、手机号赠送或第三方平台转赠双11 Plus优惠券:首先确认优惠券支持赠送,再通过APP【赠送朋友】功能分享链接,或在Plus会员专区输入亲友手机号定向赠送,也可借助高省等返利平台生成链接实现转赠并获取返利。 如果您在京东双11期间获得了Plus会员优惠券,并希望将其转赠给亲友以共享…

    2026年9月26日 • 用户投稿
    000
  • Laravel服务容器的绑定与解析

    本篇文章给大家带来的内容是关于laravel服务容器的绑定与解析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 前言   老实说,第一次老大让我看laravel框架手册的那天早上,我是很绝望的,因为真的没接触过,对我这种渣渣来说,laravel的入门门槛确实有点高了,但还是得硬着头…

    2026年9月26日
    100
  • 小红书网页版怎么安全退出_小红书网页版账号安全退出教程

    小红书网页版怎么安全退出_小红书网页版账号安全退出教程小红书网页版怎么安全退出_小红书网页版账号安全退出教程小红书网页版怎么安全退出_小红书网页版账号安全退出教程小红书网页版怎么安全退出_小红书网页版账号安全退出教程

    小红书网页版安全退出需点击右上角头像,在下拉菜单中选择“退出登录”,退出后建议清除浏览器缓存与历史记录,并关闭无痕浏览窗口,同时定期修改密码、开启短信验证以提升账号安全性。 小红书网页版怎么安全退出?这是不少网友在使用公共设备或共享电脑时常关注的问题,接下来由PHP小编为大家带来小红书网页版账号安全…

    2026年9月26日 • 用户投稿
    200
  • 饿了么周末优惠券领取入口_饿了么周末外卖折扣领取方法

    饿了么周末优惠券领取入口_饿了么周末外卖折扣领取方法饿了么周末优惠券领取入口_饿了么周末外卖折扣领取方法饿了么周末优惠券领取入口_饿了么周末外卖折扣领取方法饿了么周末优惠券领取入口_饿了么周末外卖折扣领取方法

    答案:可通过周末红包活动、搜索“本地宝”口令、关注第三方公众号及开通饿了么会员四种方式获取周末优惠券。首先在饿了么App内参与【周末红包节】领取最高66元组合红包;其次通过搜索【本地宝】获取区域专属6-10元限时券;再者关注【外卖优惠哥】等公众号获取自动推送的领券链接与返利;最后开通饿了么会员享受每…

    2026年9月26日 • 用户投稿
    000
  • laravel框架中超实用的功能介绍

    本篇文章给大家带来的内容是关于laravel框架中超实用的功能介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 让lumen的dd() dump()像laravel一样优雅 composer require symfony/var-dumper 获取执行的sql语句 可查看sql…

    2026年9月26日
    000
  • 淘宝奥莱折扣商城是正品?怎么取消订单?订单取消全流程解析:从6重资质审核到15天价保,手把手教你破解15%纠纷率与48小时退款陷阱!

    淘宝奥莱折扣商城是正品?怎么取消订单?订单取消全流程解析:从6重资质审核到15天价保,手把手教你破解15%纠纷率与48小时退款陷阱!淘宝奥莱折扣商城是正品?怎么取消订单?订单取消全流程解析:从6重资质审核到15天价保,手把手教你破解15%纠纷率与48小时退款陷阱!淘宝奥莱折扣商城是正品?怎么取消订单?订单取消全流程解析:从6重资质审核到15天价保,手把手教你破解15%纠纷率与48小时退款陷阱!淘宝奥莱折扣商城是正品?怎么取消订单?订单取消全流程解析:从6重资质审核到15天价保,手把手教你破解15%纠纷率与48小时退款陷阱!

    在淘宝搜索“品牌折扣”时,奥莱折扣商城常以极具吸引力的低价赢得消费者关注。然而,“商品是不是正品?”“怎么取消订单?”等问题也让不少买家心存顾虑。本文结合平台规则与实际操作经验,带您全面了解淘宝奥莱折扣商城的真实情况。 一、淘宝奥莱折扣商城卖的是正品吗? 1. 平台准入审核机制 根据淘宝最新规定:未…

    2026年9月26日 • 用户投稿
    000
  • sublime怎么配置graphql语法和自动补全_sublime GraphQL语法与自动补全配置

    sublime怎么配置graphql语法和自动补全_sublime GraphQL语法与自动补全配置sublime怎么配置graphql语法和自动补全_sublime GraphQL语法与自动补全配置sublime怎么配置graphql语法和自动补全_sublime GraphQL语法与自动补全配置sublime怎么配置graphql语法和自动补全_sublime GraphQL语法与自动补全配置

    首先安装GraphQL语法高亮插件,通过Package Control搜索并安装GraphQL或GraphQL Syntax;然后安装LSP插件,配置LSP使用GraphQL Language Service,并在项目根目录创建包含schemaPath和endpoint的.graphqlconfig…

    2026年9月26日 • 用户投稿
    000
  • laravel框架的中间件middleware的详解

    laravel框架的中间件middleware的详解laravel框架的中间件middleware的详解laravel框架的中间件middleware的详解laravel框架的中间件middleware的详解

    本篇文章给大家带来的内容是关于laravel框架的中间件middleware的详解,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 laravel中间件是个非常方便的东西,能将一些逻辑实现解耦,并且在laravel中,中间件的编写也是非常的方便。谁用谁知道。 1.装饰器模式 lara…

    2026年9月26日 • 用户投稿
    100
  • firefox官网首页入口 火狐浏览器手机版免费下载地址

    firefox官网首页入口 火狐浏览器手机版免费下载地址firefox官网首页入口 火狐浏览器手机版免费下载地址firefox官网首页入口 火狐浏览器手机版免费下载地址firefox官网首页入口 火狐浏览器手机版免费下载地址

    火狐浏览器官网首页入口是https://www.mozilla.org/zh-CN/firefox/new/,该页面提供手机版免费下载链接,并介绍其核心特性如阻止跟踪器、沙盒技术、多设备同步和隐私浏览模式。 firefox官网首页入口在哪里?这是不少网友都关注的,接下来由PHP小编为大家带来火狐浏览…

    2026年9月26日 • 用户投稿
    100
  • Larave框架下Contracts契约的解析

    本篇文章给大家带来的内容是关于larave框架下contracts契约的解析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 Contracts Laravel 的契约是一组定义框架提供的核心服务的接口, 例如我们在介绍用户认证的章节中到的用户看守器契约IllumninateCont…

    2026年9月26日
    100
  • laravel如何创建自定义的Artisan命令_Laravel自定义Artisan命令教程

    答案:在 Laravel 中创建自定义 Artisan 命令可自动化常用任务,使用 make:command 生成命令类,配置 signature 和 description 属性定义调用方式与描述,于 handle() 方法编写逻辑,通过 argument() 和 option() 获取参数与选项…

    2026年9月26日
    100
  • sublime怎么给vue文件设置高亮_sublime Vue文件语法高亮设置

    sublime怎么给vue文件设置高亮_sublime Vue文件语法高亮设置sublime怎么给vue文件设置高亮_sublime Vue文件语法高亮设置sublime怎么给vue文件设置高亮_sublime Vue文件语法高亮设置sublime怎么给vue文件设置高亮_sublime Vue文件语法高亮设置

    Sublime Text 默认不支持 Vue 文件的语法高亮,但可以通过安装插件来实现。Vue 文件是混合语法(HTML、JavaScript、CSS),需要专门的语法定义才能正确高亮。以下是设置步骤: 1. 安装 Package Control(如未安装) 如果还没安装 Package Contr…

    2026年9月26日 • 用户投稿
    100

发表回复

登录后才能评论
关注微信