'', 'regional' => 'oss-cn-shanghai', 'accessKeyId' => '', 'accessKeySecret' => '', 'is_internal' => 'false', 'nothumb' => 'false', // 是否上传缩略图 'nolocalsaving' => 'false', // 是否保留本地备份 'upload_url_path' => '', // URL前缀 'style' => '', // 图片处理 'update_file_name' => 'false', // 是否重命名文件名 ); add_option('oss_options', $options, '', 'yes'); } function oss_get_client() { $oss_opt = get_option('oss_options', true); $accessKeyId = esc_attr($oss_opt['accessKeyId']); $accessKeySecret = esc_attr($oss_opt['accessKeySecret']); $endpoint = oss_get_bucket_endpoint($oss_opt); return new OssClient($accessKeyId, $accessKeySecret, $endpoint); } function oss_get_bucket_endpoint($oss_option) { $oss_regional = esc_attr($oss_option['regional']); if ($oss_option['is_internal'] == 'true') { return $oss_regional . '-internal.aliyuncs.com'; } return $oss_regional . '.aliyuncs.com'; } function oss_get_bucket_name() { $oss_opt = get_option('oss_options', true); return $oss_opt['bucket']; } /** * @param $object * @param $file * @param false $no_local_file */ function oss_file_upload($object, $file, $no_local_file = false) { //如果文件不存在,直接返回false if (!@file_exists($file)) { return false; } $bucket = oss_get_bucket_name(); $ossClient = oss_get_client(); try{ $ossClient->uploadFile($bucket, ltrim($object, "/"), $file); } catch (OssException $e) { if (WP_DEBUG) { echo 'Error Message: ', $e->getMessage(), PHP_EOL, 'Error Code: ', $e->getCode(); } } if ($no_local_file) { oss_delete_local_file($file); } } /** * 是否需要删除本地文件 * * @return bool */ function oss_is_delete_local_file() { $oss_options = get_option('oss_options', true); return (esc_attr($oss_options['nolocalsaving']) == 'true'); } /** * 删除本地文件 * * @param $file * @return bool */ function oss_delete_local_file($file) { try { //文件不存在 if (!@file_exists($file)) { return true; } //删除文件 if (!@unlink($file)) { return false; } return true; } catch (\Exception $ex) { return false; } } /** * 删除oss中的单个文件 * * @param string $file */ function oss_delete_oss_file($file) { try { $bucket = oss_get_bucket_name(); $ossClient = oss_get_client(); $ossClient->deleteObject($bucket, $file); } catch (\Throwable $e) { if (WP_DEBUG) { echo 'Error Message: ', $e->getMessage(), PHP_EOL, 'Error Code: ', $e->getCode(); } } } /** * 批量删除文件 * @param array $files */ function oss_delete_oss_files(array $files) { try { $bucket = oss_get_bucket_name(); $ossClient = oss_get_client(); $ossClient->deleteObjects($bucket, $files); } catch (\Throwable $e) { if (WP_DEBUG) { echo 'Error Message: ', $e->getMessage(), PHP_EOL, 'Error Code: ', $e->getCode(); } } } /** * 上传附件(包括图片的原图) * * @param $metadata * @return array() */ function oss_upload_attachments($metadata) { $mime_types = get_allowed_mime_types(); $image_mime_types = array( $mime_types['jpg|jpeg|jpe'], $mime_types['gif'], $mime_types['png'], $mime_types['bmp'], $mime_types['tiff|tif'], $mime_types['ico'], ); // 例如mp4等格式 上传后根据配置选择是否删除 删除后媒体库会显示默认图片 点开内容是正常的 // 图片在缩略图处理 if (!in_array($metadata['type'], $image_mime_types)) { //生成object在oss中的存储路径 if (get_option('upload_path') == '.') { $metadata['file'] = str_replace('./', '', $metadata['file']); } $object = str_replace("\\", '/', $metadata['file']); $home_path = get_home_path(); $object = str_replace($home_path, '', $object); //在本地的存储路径 $file = $home_path . $object; //向上兼容,较早的WordPress版本上$metadata['file']存放的是相对路径 //执行上传操作 oss_file_upload('/' . $object, $file, oss_is_delete_local_file()); } return $metadata; } //避免上传插件/主题时出现同步到oss的情况 if (substr_count($_SERVER['REQUEST_URI'], '/update.php') <= 0) { add_filter('wp_handle_upload', 'oss_upload_attachments', 50); } /** * 上传图片的缩略图 */ function oss_upload_thumbs($metadata) { //获取上传路径 $wp_uploads = wp_upload_dir(); $basedir = $wp_uploads['basedir']; //获取oss插件的配置信息 $oss_options = get_option('oss_options', true); if (isset($metadata['file'])) { // Maybe there is a problem with the old version $file = $basedir . '/' . $metadata['file']; $upload_path = get_option('upload_path'); if ($upload_path != '.') { $path_array = explode($upload_path, $file); if (isset($path_array[1]) && !empty($path_array[1])) { $object = '/' . $upload_path . $path_array[1]; } } else { $object = '/' . $metadata['file']; $file = str_replace('./', '', $file); } oss_file_upload($object, $file, (esc_attr($oss_options['nolocalsaving']) == 'true')); } //上传所有缩略图 if (isset($metadata['sizes']) && count($metadata['sizes']) > 0) { //是否需要上传缩略图 $nothumb = (esc_attr($oss_options['nothumb']) == 'true'); //如果禁止上传缩略图,就不用继续执行了 if ($nothumb) { return $metadata; } //得到本地文件夹和远端文件夹 $file_path = $basedir . '/' . dirname($metadata['file']) . '/'; $file_path = str_replace("\\", '/', $file_path); if ($upload_path == '.') { $file_path = str_replace('./', '', $file_path); } $object_path = str_replace(get_home_path(), '', $file_path); //there may be duplicated filenames,so .... foreach ($metadata['sizes'] as $val) { //生成object在oss中的存储路径 $object = '/' . $object_path . $val['file']; //生成本地存储路径 $file = $file_path . $val['file']; //执行上传操作 oss_file_upload($object, $file, (esc_attr($oss_options['nolocalsaving']) == 'true')); } } return $metadata; } //避免上传插件/主题时出现同步到oss的情况 if (substr_count($_SERVER['REQUEST_URI'], '/update.php') <= 0) { add_filter('wp_generate_attachment_metadata', 'oss_upload_thumbs', 100); } /** * 删除远端文件,删除文件时触发 * @param $post_id */ function oss_delete_remote_attachment($post_id) { // 获取图片类附件的meta信息 $meta = wp_get_attachment_metadata( $post_id ); if (isset($meta['file'])) { $deleteObjects = []; // meta['file']的格式为 "2020/01/wp-bg.png" $upload_path = get_option('upload_path'); if ($upload_path == '') { $upload_path = 'wp-content/uploads'; } $file_path = $upload_path . '/' . $meta['file']; $deleteObjects[] = str_replace("\\", '/', $file_path); // $oss_options = get_option('oss_options', true); // $is_nothumb = (esc_attr($oss_options['nothumb']) == 'false'); // if ($is_nothumb) { // 删除缩略图 if (isset($meta['sizes']) && count($meta['sizes']) > 0) { foreach ($meta['sizes'] as $val) { $size_file = dirname($file_path) . '/' . $val['file']; $deleteObjects[] = str_replace("\\", '/', $size_file); } } // } oss_delete_oss_files($deleteObjects); } else { // 获取链接删除 $link = wp_get_attachment_url($post_id); if ($link) { $upload_path = get_option('upload_path'); if ($upload_path != '.') { $file_info = explode($upload_path, $link); if (isset($file_info[1])) { oss_delete_oss_file($upload_path . $file_info[1]); } } else { $oss_options = get_option('oss_options', true); $oss_upload_url = esc_attr($oss_options['upload_url_path']); $file_info = explode($oss_upload_url, $link); if (isset($file_info[1])) { oss_delete_oss_file($file_info[1]); } } } } } add_action('delete_attachment', 'oss_delete_remote_attachment'); // 当upload_path为根目录时,需要移除URL中出现的“绝对路径” function oss_modefiy_img_url($url, $post_id) { // 移除 ./ 和 项目根路径 $url = str_replace(array('./', get_home_path()), array('', ''), $url); return $url; } if (get_option('upload_path') == '.') { add_filter('wp_get_attachment_url', 'oss_modefiy_img_url', 30, 2); } function oss_sanitize_file_name($filename) { $oss_options = get_option('oss_options'); switch ($oss_options['update_file_name']) { case 'md5': return md5($filename) . '.' . pathinfo($filename, PATHINFO_EXTENSION); case 'time': return date('YmdHis', current_time('timestamp')) . mt_rand(100, 999) . '.' . pathinfo($filename, PATHINFO_EXTENSION); default: return $filename; } } add_filter( 'sanitize_file_name', 'oss_sanitize_file_name', 10, 1 ); function oss_function_each(&$array) { $res = array(); $key = key($array); if ($key !== null) { next($array); $res[1] = $res['value'] = $array[$key]; $res[0] = $res['key'] = $key; } else { $res = false; } return $res; } /** * @param $dir * @return array */ function oss_read_dir_queue($dir) { $dd = []; if (isset($dir)) { $files = array(); $queue = array($dir); while ($data = oss_function_each($queue)) { $path = $data['value']; if (is_dir($path) && $handle = opendir($path)) { while ($file = readdir($handle)) { if ($file == '.' || $file == '..') { continue; } $files[] = $real_path = $path . '/' . $file; if (is_dir($real_path)) { $queue[] = $real_path; } //echo explode(get_option('upload_path'),$path)[1]; } } closedir($handle); } $upload_path = get_option('upload_path'); foreach ($files as $v) { if (!is_dir($v)) { $dd[] = ['filepath' => $v, 'key' => '/' . $upload_path . explode($upload_path, $v)[1]]; } } } return $dd; } // 在插件列表页添加设置按钮 function oss_plugin_action_links($links, $file) { if ($file == plugin_basename(dirname(__FILE__) . '/aliyun-oss-wordpress.php')) { $links[] = '设置'; $links[] = '赞赏'; } return $links; } add_filter('plugin_action_links', 'oss_plugin_action_links', 10, 2); add_filter('the_content', 'oss_setting_content_style'); function oss_setting_content_style($content) { $option = get_option('oss_options'); if (!empty($option['style'])) { preg_match_all('//sim', $content, $images); if (!empty($images) && isset($images[1])) { $images[1] = array_unique($images[1]); foreach ($images[1] as $item) { if((strpos($item, $option['upload_url_path']) !== false) && (strpos($item, $option['style']) === false)){ $content = str_replace($item, $item . $option['style'], $content); } } } } return $content; } add_filter('post_thumbnail_html', 'oss_setting_post_thumbnail_style', 10, 3); function oss_setting_post_thumbnail_style( $html, $post_id, $post_image_id ) { $option = get_option('oss_options'); if (!empty($option['style']) && has_post_thumbnail()) { preg_match_all('//sim', $html, $images); if (!empty($images) && isset($images[1])) { $images[1] = array_unique($images[1]); foreach ($images[1] as $item) { if((strpos($item, $option['upload_url_path']) !== false) && (strpos($item, $option['style']) === false)){ $html = str_replace($item, $item . $option['style'], $html); } } } } return $html; } // 在导航栏“设置”中添加条目 function oss_add_setting_page() { add_options_page('阿里云OSS设置', '阿里云OSS设置', 'manage_options', __FILE__, 'oss_setting_page'); } add_action('admin_menu', 'oss_add_setting_page'); // 插件设置页面 function oss_setting_page() { if (!current_user_can('manage_options')) { wp_die('Insufficient privileges!'); } $options = array(); if (!empty($_POST) and $_POST['type'] == 'oss_set') { $options['bucket'] = isset($_POST['bucket']) ? sanitize_text_field($_POST['bucket']) : ''; $options['regional'] = isset($_POST['regional']) ? sanitize_text_field($_POST['regional']) : ''; $options['accessKeyId'] = isset($_POST['accessKeyId']) ? sanitize_text_field($_POST['accessKeyId']) : ''; $options['accessKeySecret'] = isset($_POST['accessKeySecret']) ? sanitize_text_field($_POST['accessKeySecret']) : ''; $options['is_internal'] = isset($_POST['is_internal']) ? 'true' : 'false'; $options['nothumb'] = isset($_POST['nothumb']) ? 'true' : 'false'; $options['nolocalsaving'] = isset($_POST['nolocalsaving']) ? 'true' : 'false'; //仅用于插件卸载时比较使用 $options['upload_url_path'] = isset($_POST['upload_url_path']) ? sanitize_text_field(stripslashes($_POST['upload_url_path'])) : ''; $options['style'] = isset($_POST['style']) ? sanitize_text_field($_POST['style']) : ''; $options['update_file_name'] = isset($_POST['update_file_name']) ? sanitize_text_field($_POST['update_file_name']) : 'false'; } if (!empty($_POST) and $_POST['type'] == 'aliyun_oss_all') { $sync = oss_read_dir_queue(get_home_path() . get_option('upload_path')); foreach ($sync as $k) { oss_file_upload($k['key'], $k['filepath']); } echo '本次操作成功同步' . count($sync) . '个文件'; } // 替换数据库链接 if(!empty($_POST) and $_POST['type'] == 'aliyun_oss_replace') { $old_url = esc_url_raw($_POST['old_url']); $new_url = esc_url_raw($_POST['new_url']); global $wpdb; $posts_name = $wpdb->prefix .'posts'; // 文章内容 $posts_result = $wpdb->query("UPDATE $posts_name SET post_content = REPLACE( post_content, '$old_url', '$new_url') "); // 修改题图之类的 $postmeta_name = $wpdb->prefix .'postmeta'; $postmeta_result = $wpdb->query("UPDATE $postmeta_name SET meta_value = REPLACE( meta_value, '$old_url', '$new_url') "); echo '替换成功!共替换文章内链'.$posts_result.'条、题图链接'.$postmeta_result.'条!'; } // 若$options不为空数组,则更新数据 if ($options !== array()) { //更新数据库 update_option('oss_options', $options); $upload_path = sanitize_text_field(trim(stripslashes($_POST['upload_path']), '/')); $upload_path = ($upload_path == '') ? ('wp-content/uploads') : ($upload_path); update_option('upload_path', $upload_path); $upload_url_path = sanitize_text_field(trim(stripslashes($_POST['upload_url_path']), '/')); update_option('upload_url_path', $upload_url_path); echo '设置已保存!'; } $oss_options = get_option('oss_options', true); $upload_path = get_option('upload_path'); $upload_url_path = get_option('upload_url_path'); $oss_bucket = esc_attr($oss_options['bucket']); $oss_regional = esc_attr($oss_options['regional']); $oss_accessKeyId = esc_attr($oss_options['accessKeyId']); $oss_accessKeySecret = esc_attr($oss_options['accessKeySecret']); $oss_is_internal = esc_attr($oss_options['is_internal']); $oss_is_internal = ($oss_is_internal == 'true'); $oss_nothumb = esc_attr($oss_options['nothumb']); $oss_nothumb = ($oss_nothumb == 'true'); $oss_nolocalsaving = esc_attr($oss_options['nolocalsaving']); $oss_nolocalsaving = ($oss_nolocalsaving == 'true'); $oss_update_file_name = esc_attr($oss_options['update_file_name']); $oss_style = esc_attr($oss_options['style']); $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? 'https://' : 'http://'; ?> 阿里云 OSS 设置 当前版本: 如果觉得此插件对你有所帮助,不妨到 GitHub 上点个Star,Watch关注更新;欢迎加入云存储插件交流群,QQ群号:887595381; Bucket名称 请先访问 阿里云控制台 创建Bucket,再填写以上内容。 区域 >华东 1(杭州) >华东 2(上海) >华北 1(青岛) >华北 2(北京) >华北 3(张家口) >华北 5(呼和浩特) >华北 6(乌兰察布) >华南 1(深圳) >华南 2(河源) >华南 3(广州) >西南 1(成都) >中国(香港) >美国西部 1 (硅谷) >美国东部 1 (弗吉尼亚) >亚太东南 1 (新加坡) >亚太东南 2 (悉尼) >亚太东南 3 (吉隆坡) >亚太东南 5 (雅加达) >亚太东北 1 (日本) >亚太南部 1 (孟买) >欧洲中部 1 (法兰克福) >英国(伦敦) >中东东部 1 (迪拜) 请选择您创建的Bucket所在区域 AccessKeyId AccessKeySecret 是否使用内网传输 /> 如果你的服务器是在阿里云并且区域和Bucket所在区域一致,请勾选。 不上传缩略图 /> 建议不勾选 不在本地保留备份 /> 建议不勾选 自动重命名文件 value="false">不处理 value="md5">MD5 value="time">时间戳+随机数 本地文件夹 附件在服务器上的存储位置,例如: wp-content/uploads (注意不要以“/”开头和结尾),根目录请输入.。 URL前缀 注意: 1)URL前缀的格式为 {OSS外网访问Bucket域名}/{本地文件夹} ,“本地文件夹”务必与上面保持一致(结尾无 / ),或者“本地文件夹”为 . 时 {OSS外网访问域名} 。 2)OSS中的存放路径(即“文件夹”)与上述 本地文件夹 中定义的路径是相同的(出于方便切换考虑)。 3)如果需要使用 用户域名 ,直接将 {OSS外网访问Bucket域名} 替换为 用户域名 即可。 图片处理 获取样式: 1)在阿里云 OSS管理控制台 对应的 Bucket 中数据处理 -> 图片处理 中新建样式。具体样式设置参考阿里云文档。 2)填写时需要将默认规则或自定义分隔符和对应的创建规则名称进行拼接,例如: ① 默认规则为?x-oss-process=style/,规则名称为stylename 则填写为 ?x-oss-process=style/stylename ② 分隔符为!(感叹号),规则名称为stylename 则填写为 !stylename 保存/更新选项 同步历史附件 注意:如果是首次同步,执行时间将会十分十分长(根据你的历史附件数量),有可能会因执行时间过长,页面显示超时或者报错。 所以,建议那些几千上万附件的大神们,考虑官方的 同步工具 数据库原链接替换 注意:如果是首次替换,请注意备份!此功能会替换文章以及设置的特色图片(题图)等使用的资源链接
本次操作成功同步' . count($sync) . '个文件
替换成功!共替换文章内链'.$posts_result.'条、题图链接'.$postmeta_result.'条!
设置已保存!
如果觉得此插件对你有所帮助,不妨到 GitHub 上点个Star,Watch关注更新;欢迎加入云存储插件交流群,QQ群号:887595381;
Star
Watch
请先访问 阿里云控制台 创建Bucket,再填写以上内容。
Bucket
请选择您创建的Bucket所在区域
如果你的服务器是在阿里云并且区域和Bucket所在区域一致,请勾选。
建议不勾选
附件在服务器上的存储位置,例如: wp-content/uploads (注意不要以“/”开头和结尾),根目录请输入.。
wp-content/uploads
.
注意:
1)URL前缀的格式为 {OSS外网访问Bucket域名}/{本地文件夹} ,“本地文件夹”务必与上面保持一致(结尾无 / ),或者“本地文件夹”为 . 时 {OSS外网访问域名} 。
{OSS外网访问Bucket域名}/{本地文件夹}
/
{OSS外网访问域名}
2)OSS中的存放路径(即“文件夹”)与上述 本地文件夹 中定义的路径是相同的(出于方便切换考虑)。
本地文件夹
3)如果需要使用 用户域名 ,直接将 {OSS外网访问Bucket域名} 替换为 用户域名 即可。
用户域名
{OSS外网访问Bucket域名}
获取样式:
1)在阿里云 OSS管理控制台 对应的 Bucket 中数据处理 -> 图片处理 中新建样式。具体样式设置参考阿里云文档。
2)填写时需要将默认规则或自定义分隔符和对应的创建规则名称进行拼接,例如:
默认规则
自定义分隔符
规则名称
① 默认规则为?x-oss-process=style/,规则名称为stylename
?x-oss-process=style/
stylename
则填写为 ?x-oss-process=style/stylename
?x-oss-process=style/stylename
② 分隔符为!(感叹号),规则名称为stylename
分隔符
!
则填写为 !stylename
!stylename
注意:如果是首次同步,执行时间将会十分十分长(根据你的历史附件数量),有可能会因执行时间过长,页面显示超时或者报错。 所以,建议那些几千上万附件的大神们,考虑官方的 同步工具
注意:如果是首次替换,请注意备份!此功能会替换文章以及设置的特色图片(题图)等使用的资源链接