wordpress优化经历(六)——wordpress图片防盗链

背景

由于我写博客的习惯是先在本地把博客写好,然后图片什么的先放在本地,之后将博客在CSDN上进行markdown排版,并且将图片上传图加进去,在CSDN上先完成博客文章的发布;最后就直接将CSDN上的排版好的文章进行复制粘贴进自己的个人博客网站上,这样做的好处就是文章不用重新排版了,然后里面的图片资源也上传到了CSDN的服务器上,之后自己网站引用图片也是使用了CSDN的图片资源。但是最近出现了一个问题,CSDN上的图片全部失效了,原因是图片被防盗链处理,请求全部被跨域访问了,导致我个人网站的所有使用过CSDN排版的博客图片全部链接失效了,这导致我很头疼,这篇文章就记录一下这次图片被防盗链事故的处理经过。

在这里插入图片描述

解决方法

WordPress很多插件或者代码都可以实现在编辑文章中自动将外链图片下载到本地,但是我试了几个效果都不是很好。
最后选择了一个比较笨一点的方法,但是效果贼好。

  1. 将下面代码加到当前主题函数模板 functions.php 中:
function ecp_save_post($post_id, $post) {
  global $wpdb;
  if($post->post_status == 'publish') {
    $p   = '/<img.*[\s]src=[\"|\'](.*)[\"|\'].*>/iU';
    $num = preg_match_all($p, $post->post_content, $matches);
    if ($num) {
      $wp_upload_dir = wp_upload_dir();
      set_time_limit(0);
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_HEADER, false);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
      curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
      curl_setopt($ch, CURLOPT_MAXREDIRS,20);
      curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
 
      $ecp_options = $_SERVER['HTTP_HOST'];
      foreach ($matches[1] as $src) {
        if (isset($src) && strpos($src, $ecp_options) === false) {
          $file_info = wp_check_filetype(basename($src), null);
          if ($file_info['ext'] == false) {
            date_default_timezone_set('PRC');
            $file_name = date('YmdHis-').dechex(mt_rand(100000, 999999)).'.tmp';
          } else {
            $file_name = dechex(mt_rand(100000, 999999)) . '-' . basename($src);
          }
          curl_setopt($ch, CURLOPT_URL, $src);
          $file_path = $wp_upload_dir['path'] . '/' . $file_name;
          $img = fopen($file_path, 'wb');
          curl_setopt($ch, CURLOPT_FILE, $img);
          $img_data  = curl_exec($ch);
          fclose($img);
 
          if (file_exists($file_path) && filesize($file_path) > 0) {
            $t   = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
            $arr = explode('/', $t);
            if (pathinfo($file_path, PATHINFO_EXTENSION) == 'tmp') {
              $file_path = ecp_handle_ext($file_path, $arr[1], $wp_upload_dir['path'], $file_name, 'tmp');
            } elseif (pathinfo($file_path, PATHINFO_EXTENSION) == 'webp') {
              $file_path = ecp_handle_ext($file_path, $arr[1], $wp_upload_dir['path'], $file_name, 'webp');
            }
            $post->post_content  = str_replace($src, $wp_upload_dir['url'] . '/' . basename($file_path), $post->post_content);
            $attachment = ecp_get_attachment_post(basename($file_path), $wp_upload_dir['url'] . '/' . basename($file_path));
            $attach_id = wp_insert_attachment($attachment, ltrim($wp_upload_dir['subdir'] . '/' . basename($file_path), '/'), 0);
            $attach_data = wp_generate_attachment_metadata($attach_id, $file_path);
            $ss = wp_update_attachment_metadata($attach_id, $attach_data);
          }
        }
      }
      curl_close($ch);
      $wpdb->update( $wpdb->posts, array('post_content' => $post->post_content), array('ID' => $post->ID));
    }
  }
}
 
function ecp_handle_ext($file, $type, $file_dir, $file_name, $ext) {
  switch ($ext) {
    case 'tmp':
      if (rename($file, str_replace('tmp', $type, $file))) {
        if ('webp' == $type) {
          return ecp_image_convert('webp', 'jpeg', $file_dir . '/' . str_replace('tmp', $type, $file_name));
        }
        return $file_dir . '/' . str_replace('tmp', $type, $file_name);
      }
    case 'webp':
      if ('webp' == $type) {
        return ecp_image_convert('webp', 'jpeg', $file);
      } else {
        if (rename($file, str_replace('webp', $type, $file))) {
          return $file_dir . '/' . str_replace('webp', $type, $file_name);
        }
      }
    default:
      return $file;
  }
}
 
function ecp_image_convert($from='webp', $to='jpeg', $image) {
  $im = imagecreatefromwebp($image);
  if (imagejpeg($im, str_replace('webp', 'jpeg', $image), 100)) {
    try {
      unlink($image);
    } catch (Exception $e) {
      $error_msg = sprintf('Error removing local file %s: %s', $image,
        $e->getMessage());
      error_log($error_msg);
    }
  }
  imagedestroy($im);
 
  return str_replace('webp', 'jpeg', $image);
}
 
function ecp_get_attachment_post($filename, $url) {
  $file_info  = wp_check_filetype($filename, null);
  return array(
    'guid'           => $url,
    'post_type'      => 'attachement',
    'post_mime_type' => $file_info['type'],
    'post_title'     => preg_replace('/\.[^.]+$/', '', $filename),
    'post_content'   => '',
    'post_status'    => 'inherit'
  );
}
add_action('save_post', 'ecp_save_post', 120, 2);
  1. 编辑更新文章

单篇操作
之后,编辑文章只需要点击更新按钮,就可以将文章中的外链图片下载到本地并替换链接。

不过逐个编辑文章不仅繁琐而且工作量不小,这里教大家一个小技巧,可以批量下载文章中的外链图片。

批量操作
该插件的代码不仅可以在正常的编辑页面点击更新按钮触发下载功能,而且可以在后台所有文章列表页面中触发下载图片功能,原理明白了,操作就简单了。

进入WP后台,文章→所有文章,进入文章管理页面,勾选“标题”全选当前页面的所有文章,并选择“编辑”,并点击“应用”按钮。
切记,不要更改批量编辑中的任何设置,只需单击 “更新”即可。
在这里插入图片描述

这个过程将触发检查所有选定的文章,并自动下载外链图片!

  1. 完成上面操作后就可以将步骤1中加入functions.php 的代码给注释掉了

推荐写文章资源处理的几个方法

由于程序员一般写博客文章啥的一般都是使用markdown,所以用对工具可以提高效率
也是为了避免防盗链,真的太可恶了

方案一(推荐)

我目前写文章打算使用自己的服务器部署的云电脑kodbox,用这个的好处是:

  1. 资源全部在云服务器上,不用担心同步问题

  2. kodbox里面有很多好用的小工具,文章编写也很方便,可以极大的提高效率

  3. 然后就是资源存储问题,由于自己服务器上的kodbox,所以不会出现防盗链的情况,然后写文章时上传图片也很方便,可以将图片复制粘贴直接上传,上传时会自动在该文章的目录下新建一个images目录,所有的资源都放在那里
    在这里插入图片描述

  4. 最后这些资源是虽然是相对路径引用的,但是可以根据自己的需求将路径更改为直连访问(该死的CSDN肯定不给直链)

方案二

如果是在本地写博客的话,首选肯定是Typora,但是Typora在资源处理上也挺麻烦的。但是可以自定义图片上传服务,目前好像只能使用PicGo当作资源服务器中端进行上传服务器,所以要上传到自己云服务器保证资源不会被防盗链就得自己另外部署一个PicGo图床项目,由于我已经使用了图床chevereto,就不想再折腾了。
在这里插入图片描述

具体可以自己折腾或者参考:https://www.bilibili.com/read/cv13781176/

方案三

当然也可以使用其他在线写文章的工具网站写文章,比如石墨文档墨滴

防盗链设置

由于本人使用七牛云多一点,就说一下七牛云的防盗链设置
在这里插入图片描述

其实就是在七牛云的后台添加Referer 防盗链白名单就可以了
具体参考官方文档:https://developer.qiniu.com//fusion/kb/1337/what-is-hotlinking-prevention-set-of-empty-referer

java开发中也可以使用Servlet进行设置防盗链
参考我之前的博客:https://qkongtao.cn/?p=389#h2-2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不愿意做鱼的小鲸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值