Laravel-admin 中 summernote 图片 base64 转文件

背景: 不喜欢数据库中存储大段的 base64 图片, 太占空间了; laravel-admin 中没找到其它特别好用的富文本编辑器, 所以改吧.

  1. 最初的想法是直接改 summernote 的 js 文件, 可是要动到 vendor 中的内容, 不想改
  2. 在表单内容存储到数据库之前 (或之后) 把 base64 的图片保存成文件, 并用文件的路径代替之前的 base64串

实现:
在 laravel-admin 的控制器中重写 store, update, destroy 方法, 前两个用于 base64 转 文件, 后一个用于删除图片

// ArticlesController.php
/********** 以下重写 store, update, destroy 方法, 用于 summernote 上传的base64图片转文件或删除 *******/
public function store()
{
    request()['content'] = summernote_base64_to_file(request()['content']);

    parent::store();
}

public function update($id)
{
    request()['content'] = summernote_base64_to_file(request()['content']);

    parent::update($id);
}

public function destroy($id)
{
    $article = Article::find($id);
    summernote_delete_image($article->content);

    parent::destroy($id);
}
    // helpers.php
    function summernote_base64_to_file($content)
    {
        if (!($content && \Str::contains($content, ['src="data:image', 'src=\'data:image']))) {
            return $content;
    }

    $pattern = '/(data:image\/)([^;]+)(;base64,)([^\"]+)/';
    $res     = preg_replace_callback($pattern, function ($matches) {
        // 生成路径
        $public_path = public_path();
        $folder_path = '/summernote/' . date('Ym') . '/' . date('d') . '/';
        if (!is_dir($dir = $public_path . $folder_path)) {
            mkdir($dir, 0777, true);
        }

        // 生成文件名
        $matches[2] = $matches[2] === 'jpeg' ? 'jpg' : $matches[2];
        $filename   = md5(time() . \Illuminate\Support\Str::random()) . '.' . $matches[2];
        $file       = $dir . $filename;

        // 保存文件
        file_put_contents($file, base64_decode($matches[4]));// base64 转图片

        // 返回相对路径
        return $folder_path . $filename;
    }, $content);

    return $res;
}

function summernote_delete_image($content)
{
    if (!($content && \Str::contains($content, ['summernote']))) {
        return null;
    }

    $pattern = '/(\/summernote[^\'\"]+)/';
    $times   = preg_match_all($pattern, $content, $matches);
    if ($times) {
        foreach ($matches[0] as $value) {
            unlink(public_path() . $value);
        }
    }
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 2

謝謝分享,我測試後發現不能正常新增article,試了大半天後發現將 parent::store(); 修改成 return parent::store(); 即可,update() 和 destroy()也需要修改。

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!