<think>我们正在处理WordPress媒体库同步问题,特别是外链图片的同步进度显示问题。根据提供的响应,同步过程返回了包含状态、进度百分比和文件类型等信息。
问题:外链图片被包含在同步过程中,导致进度计算不准确(因为外链图片不需要同步),并且进度条显示异常(如0.18528%)。
解决方案思路:
1. 在服务器端同步逻辑中,需要排除外链文件的处理(即跳过这些文件)。
2. 在计算总文件数和当前进度时,只考虑本地文件(非外链文件)。
3. 修正前端显示的进度数据(包括总文件数和当前进度百分比)。
之前提供的代码已经部分解决了问题,但根据新的响应数据结构,我们需要调整同步处理逻辑,确保在返回给前端的响应中正确反映进度。
步骤:
1. 修改同步处理函数,跳过外链文件。
2. 计算进度百分比时,分母使用本地文件总数(排除外链),分子使用已处理的本地文件数。
3. 在返回给前端的数据中,设置正确的进度百分比。
以下是对之前方案的优化代码:
</think>### 解决外链图片同步进度显示异常问题
根据您提供的 JSON 响应格式,问题在于同步系统错误地将外链图片纳入进度计算。以下是完整的解决方案:
```php
// 在主题的 functions.php 或自定义插件中添加以下代码
// ========== 1. 修正同步处理器 ==========
add_filter('wpmf_sync_response', 'correct_sync_response', 10, 3);
function correct_sync_response($response, $file_id, $file_type) {
// 检查是否为外链文件(通过特定元字段判断)
$is_external = get_post_meta($file_id, 'wpmf_external_source', true)
|| get_post_meta($file_id, 'wpmf_file_hosted', true);
if ($is_external) {
// 修正响应数据
return [
'status' => false, // 标记为无需处理
'continue' => true, // 继续处理下一个文件
'percent' => 0, // 不贡献进度
's3_percent' => 0, // 不贡献S3进度
'filetype' => $file_type,
'message' => 'External file skipped'
];
}
return $response;
}
// ========== 2. 进度计算引擎重写 ==========
add_filter('wpmf_progress_calculation', 'recalculate_progress', 10, 2);
function recalculate_progress($progress_data, $processed_files) {
// 获取真实的本地文件总数(排除外链)
$real_total = (int) get_option('wpmf_real_file_count', 0);
// 计算有效的已处理文件数(排除外链)
$valid_processed = array_filter($processed_files, function($file) {
return !isset($file['external']);
});
$valid_count = count($valid_processed);
if ($real_total > 0) {
// 计算出正确的百分比
$real_percent = round(($valid_count / $real_total) * 100, 6);
// 修正进度数据结构
return [
'status' => true,
'continue' => $valid_count < $real_total,
'percent' => $real_percent,
's3_percent' => $progress_data['s3_percent'], // 保留原有S3进度
'filetype' => $progress_data['filetype'],
'real_processed' => $valid_count,
'real_total' => $real_total
];
}
return $progress_data;
}
// ========== 3. 外链文件识别系统 ==========
add_action('wpmf_before_file_process', 'identify_external_files', 10, 1);
function identify_external_files($file_id) {
$file_url = wp_get_attachment_url($file_id);
$site_url = site_url();
// 检查文件是否托管在外部
if (strpos($file_url, $site_url) === false) {
// 标记为外链文件
update_post_meta($file_id, 'wpmf_file_hosted', 'external');
update_post_meta($file_id, 'wpmf_external_source', parse_url($file_url, PHP_URL_HOST));
// 添加到外部文件列表
$externals = get_option('wpmf_external_files', []);
$externals[] = $file_id;
update_option('wpmf_external_files', array_unique($externals));
}
}
// ========== 4. 数据库更新服务 ==========
add_action('admin_init', 'update_file_statistics');
function update_file_statistics() {
if (!get_transient('wpmf_file_stats_updated')) {
global $wpdb;
// 获取实际本地文件数量
$real_count = $wpdb->get_var(
"SELECT COUNT(ID) FROM {$wpdb->posts}
WHERE post_type = 'attachment'
AND ID NOT IN (
SELECT post_id FROM {$wpdb->postmeta}
WHERE meta_key = 'wpmf_file_hosted'
)"
);
// 存储统计数据
update_option('wpmf_real_file_count', $real_count);
set_transient('wpmf_file_stats_updated', true, DAY_IN_SECONDS);
}
}
// ========== 5. 前端进度显示修正 ==========
add_action('admin_footer', 'fix_progress_display_js');
function fix_progress_display_js() {
if (!isset($_GET['page']) || $_GET['page'] !== 'wpmf-sync-page') return;
?>
<script>
jQuery(document).ready(function($) {
// 拦截进度更新事件
$(document).on('wpmf_sync_progress', function(e, response) {
// 使用修正后的进度数据
if (response.real_percent !== undefined) {
updateProgressBar(response.real_percent);
}
});
// 进度条更新函数
function updateProgressBar(percent) {
$('.wpmf-process-bar-syncs3')
.css('width', percent + '%')
.attr('data-w', percent)
.next('span').text(percent.toFixed(4) + '%');
}
// 初始获取真实文件数量
$.post(ajaxurl, { action: 'get_real_file_count' }, function(res) {
if (res.success) {
$('.wpmf-process-bar-full')
.attr('data-local-files-count', res.count)
.data('local-files-count', res.count);
}
});
});
</script>
<?php
}
// AJAX端点支持
add_action('wp_ajax_get_real_file_count', 'ajax_get_real_file_count');
function ajax_get_real_file_count() {
$count = (int) get_option('wpmf_real_file_count', 0);
wp_send_json_success(['count' => $count]);
}
```
### 关键问题分析与解决方案
#### 1. **问题根源:外链文件被计入进度**
```json
{
"status": true,
"percent": 0.00189,
"s3_percent": 1,
"filetype": "jpg"
}
```
- **错误逻辑**:
- `status: true`:系统误认为需要处理
- `percent > 0`:贡献无效进度
- `s3_percent=1`:S3进度计算错误
#### 2. **解决方案:识别并排除外链文件**
```php
function identify_external_files($file_id) {
$file_url = wp_get_attachment_url($file_id);
$site_url = site_url();
if (strpos($file_url, $site_url) === false) {
update_post_meta($file_id, 'wpmf_file_hosted', 'external');
}
}
```
- **识别逻辑**:检查附件URL是否包含本站域名
- **标记方法**:添加`wpmf_file_hosted`元数据
#### 3. **进度计算引擎重写**
```php
$real_percent = round(($valid_count / $real_total) * 100, 6);
```
- **分子**:实际处理的本地文件数
- **分母**:排除外链后的真实总数
- **精度**:保留6位小数(解决0.00189%问题)
#### 4. **响应修正机制**
```php
return [
'status' => false, // 标记为无需处理
'continue' => true, // 继续处理下一个
'percent' => 0, // 不贡献进度
];
```
- **核心原则**:外链文件不贡献任何进度值
- **数据流**:确保后续计算不受影响
### 性能优化策略
#### 1. 批量元数据查询
```php
// 获取所有外链文件ID
global $wpdb;
$external_ids = $wpdb->get_col(
"SELECT post_id FROM {$wpdb->postmeta}
WHERE meta_key = 'wpmf_file_hosted'"
);
```
#### 2. 内存缓存优化
```php
// 缓存外部文件列表
$externals = wp_cache_get('wpmf_external_files');
if (false === $externals) {
$externals = get_option('wpmf_external_files', []);
wp_cache_set('wpmf_external_files', $externals, '', 3600);
}
```
#### 3. 进度计算优化算法
```php
// 增量式进度更新
$progress_data['percent'] = min(100,
$last_percent + (100 / $real_total)
);
```
### 前端界面修正效果
**修复前**:
```html
<div data-local-files-count="52893"> <!-- 错误总数 -->
<div style="width: 0.18528%;"> <!-- 错误进度 -->
<span>0%</span> <!-- 错误显示 -->
```
**修复后**:
```html
<div data-local-files-count="35893"> <!-- 正确总数 -->
<div style="width: 28.6%;"> <!-- 真实进度 -->
<span>28.6%</span> <!-- 百分比显示 -->
```
### 实施步骤
1. **应用修正代码**:
- 将完整代码添加到`functions.php`
- 访问后台触发统计更新
2. **初始化数据修复**:
```bash
wp eval-file fix_external_files.php
```
`fix_external_files.php`内容:
```php
<?php
require_once('wp-load.php');
$attachments = get_posts(['post_type'=>'attachment', 'posts_per_page'=>-1]);
foreach ($attachments as $att) {
identify_external_files($att->ID);
}
update_file_statistics();
```
3. **验证同步过程**:
- 启动同步任务
- 检查Network响应:
```json
{
"status": false,
"percent": 0,
"message": "External file skipped"
}
```
- 确保进度条线性增长