前言

事情还得从几天前心血来潮准备水一篇文章说起。
我喜欢使用win10的屏幕截图,然后直接用 Ctrl + V的方式粘贴到WP-Editor.MD里,编辑器就自动获取剪贴板的图片并上传。

以前用着一直都挺好的,直到这一次,我从微信右键复制的截图再也粘贴不了了,wordpress一直提示报错。于是我git clone了WP-Editor.md的源码...

找到问题

根据百度的指引,很快就找到剪贴板图片上传的相关代码
然后,找到了这段代码,判断不是png就返回error

再回去看一下报错的post提交的数据,草

对判断的小改进

接下来的问题就很简单了,我想要剪贴板上传jpeg,只需要在判断内容里加 image/jpeg 就完事了。
但是,个人觉得这种靠客户端post上来的头就判断文件确实很不妥,很容易被伪造上传,于是引入了通过幻数对传入二进制检测的composer依赖php-mime-detector

因为php-mime-detector只能通过直接传入文件的绝对地址检测,而我们post直接上传的是二进制流,所以对Mine的类进行了方法重写

class myMine extends MimeDetector
{
    function setBytes($base64)
    {
        if (empty($base64)) {
            throw new MimeDetectorException('Oh,Shit! Mei You Chuang Ru Value.');
        }
        $fileHash = $this->getHash($base64);
        if ($this->getFileHash() !== $fileHash) {
            $this->byteCache = [];
            $this->byteCacheLen = 0;
            $this->maxByteCacheLen = $this->getByteCacheMaxLength() ?: 4096;
//              $this->file = $filePath;
            $this->fileHash = $fileHash;
            $data = substr(base64_decode($base64), 0, $this->maxByteCacheLen);

            foreach (str_split($data) as $i => $char) {
                $this->byteCache[$i] = ord($char);
            }
            $this->byteCacheLen = count($this->byteCache);
        }


        return $this;
    }

    function getFileType(): array
    {
        return parent::getFileType(); // TODO: Change the autogenerated stub
    }
}

(拼音英语混合,专治低血压哈哈哈)

自动转webp

剩下的就是把原来Editor.md 默认的png转jpg压50质量的代码给突突了
换成webp
1.6M的png,webp设置原图90%质量可以压到几百k,而且webp现在几乎所有的现代浏览器均支持了,效果还好,为什么还要用糊糊的jpg呢

private function editormd_img2webp($filePath, $deleteOldFile = true)
    {
        $quality = 90;
        $newFilename = str_replace("." . $this->extension, ".webp", $filePath);
        if($this->extension == "png"){
            $image = imagecreatefrompng($filePath);
        }
        if($this->extension == "jpg"){
            $image = imagecreatefromjpeg($filePath);
        }
        $bg = imagecreatetruecolor(imagesx($image), imagesy($image));

        imagefill($bg, 0, 0, imagecolorallocate($bg, 255, 255, 255));
        imagealphablending($bg, TRUE);
        imagecopy($bg, $image, 0, 0, 0, 0, imagesx($image), imagesy($image));
        imagedestroy($image);

        imagewebp($bg, $newFilename, $quality);
        imagedestroy($bg);
        $this->extension = "webp";
        if ($deleteOldFile) {
            unlink($filePath);
        }

        return $newFilename;
    }

自动插入媒体库

这部分的代码是直接白嫖别人的,在此表示感谢
给WP Editor.md编辑器添加粘贴图片自动上传到媒体库功能
我把原作者的代码分离出来,写成函数,方便调用

private function attachment_metadata($fileUrl)
    {
        try {
            // Check the type of file. We'll use this as the 'post_mime_type'.
            $filetype = wp_check_filetype(basename($fileUrl), null);

            $attachment = array(
                'guid' => $fileUrl,
                'post_mime_type' => $filetype['type'],
                'post_title' => $this->name,
                'post_content' => '',
                'post_status' => 'inherit'
            );//文件属性
            // 插入附件信息
            $post_id = explode("&", explode("post=", wp_get_referer())[1])[0];//从request请求头refer中获取post_id
            $attach_id = wp_insert_attachment($attachment, $fileUrl, $post_id);
            // Make sure that $this file is included, as wp_generate_attachment_metadata() depends on it.
            require_once(ABSPATH . 'wp-admin/includes/image.php');

            // Generate the metadata for the attachment, and update the database record.

            $attach_data = wp_generate_attachment_metadata($attach_id, $fileUrl);
            wp_update_attachment_metadata($attach_id, $attach_data);
        } catch (Exception $e) {
            return false;
        }
        return $attach_data;
    }

遗憾

看到Editor.md对post的图片是把二进制转base64再上传,对于几M的png确实很不友好,本来想弄个前端压缩一下再上传,找了一个pako.js进行压缩,遗憾的是前端压缩过图片反而更大了,我也不知道这是神马情况

压缩前:275213

压缩后:304939

喵喵喵?或许前端先把png转成webp再上传更好?


代码萌新,热爱折腾,喜欢花草和养鱼