首页 / 应用软件 / 一步步实现,为网站添加文件上传与云存储管理

一步步实现,为网站添加文件上传与云存储管理

一步步实现:为网站添加文件上传与云存储管理,通过WordPress程序的代码二次开发实现常用互联网小工具功能

引言:为什么网站需要文件上传与云存储管理?

在当今数字化时代,网站的功能性需求日益复杂。无论是企业官网、个人博客,还是电子商务平台,文件上传与管理功能已成为不可或缺的基础需求。用户期望能够轻松上传图片、文档、视频等内容,而网站管理员则需要高效、安全地管理这些文件资源。

传统的WordPress媒体库虽然提供了基础的文件上传功能,但在面对大量文件、大文件上传、多用户协作、跨平台访问等复杂场景时,往往显得力不从心。云存储解决方案的出现,为这一问题提供了完美的答案。通过将文件存储在云端,网站不仅可以减轻服务器负担,还能实现更高的可用性、可扩展性和安全性。

本文将深入探讨如何通过WordPress代码二次开发,为网站添加强大的文件上传与云存储管理功能,并在此基础上实现一系列常用互联网小工具,从而大幅提升网站的功能性和用户体验。

第一部分:WordPress文件上传机制深度解析

1.1 WordPress默认上传系统的工作原理

WordPress内置了一个相对完整的文件上传系统。当用户通过媒体上传界面或相关功能上传文件时,系统会执行以下关键步骤:

  • 文件验证:检查文件类型、大小是否符合系统设置
  • 安全处理:对文件名进行清理,防止安全漏洞
  • 存储处理:将文件保存到wp-content/uploads目录,并按年月组织子目录
  • 数据库记录:在wp_posts表中创建attachment类型的记录
  • 元数据生成:为图片文件生成缩略图,提取EXIF信息等

了解这一基础流程是进行二次开发的前提。我们可以通过分析wp_handle_upload()、media_handle_upload()等核心函数,掌握WordPress处理上传文件的完整机制。

1.2 现有上传系统的局限性

尽管WordPress默认系统能够满足基本需求,但在实际应用中存在明显不足:

  • 存储空间受限:依赖服务器本地存储,空间有限且不易扩展
  • 性能瓶颈:大文件上传和处理可能拖慢网站响应速度
  • 备份困难:文件分散在服务器上,难以实现统一备份和恢复
  • 访问限制:缺乏细粒度的访问控制和权限管理
  • 多站点管理复杂:对于多站点网络,文件管理变得异常复杂

这些局限性正是我们需要引入云存储解决方案的根本原因。

第二部分:云存储集成方案选择与比较

2.1 主流云存储服务概览

目前市场上有多种云存储服务可供选择,每种都有其特点和适用场景:

  • Amazon S3:功能全面,生态系统完善,适合企业级应用
  • Google Cloud Storage:与Google生态系统深度集成,性能优异
  • 阿里云OSS:国内访问速度快,符合中国法规要求
  • 腾讯云COS:性价比高,与腾讯生态整合良好
  • Backblaze B2:价格实惠,适合个人和小型企业
  • Wasabi:无出口费用,适合高频访问场景

2.2 选择云存储服务的关键考量因素

在选择云存储服务时,需要综合考虑以下因素:

  • 成本结构:存储费用、请求费用、流量费用的综合评估
  • 性能表现:上传下载速度、延迟、可用性保证
  • 地理位置:服务器位置对访问速度的影响
  • 集成难度:API的易用性和文档完整性
  • 合规要求:数据主权、隐私保护等法规遵从性
  • 生态系统:与其他服务的集成能力

2.3 WordPress云存储插件评估

在开始自定义开发前,了解现有插件解决方案是必要的:

  • WP Offload Media:功能全面,支持多种云服务
  • Media Cloud:专注于云存储,提供高级功能
  • Stateless:与Google Cloud Platform深度集成
  • Storage for WordPress:轻量级解决方案,易于定制

虽然这些插件提供了现成的解决方案,但通过自定义开发,我们可以实现更贴合特定需求、更高效集成的文件管理系统。

第三部分:构建自定义文件上传与云存储管理系统

3.1 系统架构设计

我们的自定义系统将采用模块化设计,主要包括以下组件:

  1. 上传处理模块:负责接收、验证和处理上传请求
  2. 云存储适配器:抽象不同云服务的API,提供统一接口
  3. 文件管理模块:提供文件的增删改查操作
  4. 权限控制系统:管理用户对文件的访问权限
  5. 缓存与优化层:提高系统性能和响应速度
  6. 管理界面:为管理员和用户提供友好的操作界面

3.2 核心代码实现

3.2.1 创建云存储适配器抽象类
<?php
/**
 * 云存储适配器抽象类
 */
abstract class Cloud_Storage_Adapter {
    protected $config;
    protected $client;
    
    public function __construct($config) {
        $this->config = $config;
        $this->initialize_client();
    }
    
    abstract protected function initialize_client();
    abstract public function upload($local_path, $remote_path, $options = []);
    abstract public function download($remote_path, $local_path);
    abstract public function delete($remote_path);
    abstract public function list_files($prefix = '', $options = []);
    abstract public function get_url($remote_path, $expires = null);
    abstract public function file_exists($remote_path);
}
3.2.2 实现S3适配器
<?php
/**
 * Amazon S3适配器实现
 */
class S3_Storage_Adapter extends Cloud_Storage_Adapter {
    protected function initialize_client() {
        $this->client = new AwsS3S3Client([
            'version' => 'latest',
            'region'  => $this->config['region'],
            'credentials' => [
                'key'    => $this->config['key'],
                'secret' => $this->config['secret'],
            ],
        ]);
    }
    
    public function upload($local_path, $remote_path, $options = []) {
        $default_options = [
            'Bucket' => $this->config['bucket'],
            'Key'    => $remote_path,
            'SourceFile' => $local_path,
            'ACL'    => 'private',
        ];
        
        $options = array_merge($default_options, $options);
        
        try {
            $result = $this->client->putObject($options);
            return [
                'success' => true,
                'url' => $result['ObjectURL'],
                'etag' => $result['ETag'],
            ];
        } catch (AwsS3ExceptionS3Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage(),
            ];
        }
    }
    
    // 其他方法实现...
}
3.2.3 创建文件上传处理器
<?php
/**
 * 文件上传处理器
 */
class File_Upload_Handler {
    private $adapter;
    private $allowed_types;
    private $max_size;
    
    public function __construct($adapter) {
        $this->adapter = $adapter;
        $this->allowed_types = get_option('allowed_upload_types', []);
        $this->max_size = get_option('max_upload_size', 10485760); // 默认10MB
    }
    
    public function handle_upload($file, $user_id, $options = []) {
        // 验证文件
        $validation = $this->validate_file($file);
        if (!$validation['valid']) {
            return $validation;
        }
        
        // 生成唯一文件名和路径
        $file_info = $this->generate_file_info($file, $user_id);
        
        // 临时保存文件
        $temp_path = $this->save_temp_file($file);
        
        // 上传到云存储
        $upload_result = $this->adapter->upload(
            $temp_path,
            $file_info['remote_path'],
            $options
        );
        
        // 清理临时文件
        unlink($temp_path);
        
        if ($upload_result['success']) {
            // 保存文件记录到数据库
            $file_id = $this->save_file_record($file_info, $user_id);
            
            return [
                'success' => true,
                'file_id' => $file_id,
                'url' => $upload_result['url'],
                'file_info' => $file_info,
            ];
        }
        
        return [
            'success' => false,
            'error' => $upload_result['error'],
        ];
    }
    
    private function validate_file($file) {
        // 检查文件大小
        if ($file['size'] > $this->max_size) {
            return [
                'valid' => false,
                'error' => '文件大小超过限制',
            ];
        }
        
        // 检查文件类型
        $file_type = wp_check_filetype($file['name']);
        if (!in_array($file_type['type'], $this->allowed_types)) {
            return [
                'valid' => false,
                'error' => '不支持的文件类型',
            ];
        }
        
        // 安全检查
        if (!wp_verify_nonce($_POST['upload_nonce'], 'file_upload')) {
            return [
                'valid' => false,
                'error' => '安全验证失败',
            ];
        }
        
        return ['valid' => true];
    }
    
    private function generate_file_info($file, $user_id) {
        $original_name = sanitize_file_name($file['name']);
        $extension = pathinfo($original_name, PATHINFO_EXTENSION);
        $unique_name = wp_generate_uuid4() . '.' . $extension;
        
        // 按用户和日期组织目录结构
        $date = date('Y/m');
        $remote_path = "uploads/{$user_id}/{$date}/{$unique_name}";
        
        return [
            'original_name' => $original_name,
            'unique_name' => $unique_name,
            'remote_path' => $remote_path,
            'extension' => $extension,
            'size' => $file['size'],
        ];
    }
    
    // 其他辅助方法...
}

3.3 数据库设计优化

为了高效管理文件元数据,我们需要创建自定义数据库表:

CREATE TABLE wp_cloud_files (
    id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
    user_id BIGINT(20) UNSIGNED NOT NULL,
    original_name VARCHAR(255) NOT NULL,
    unique_name VARCHAR(255) NOT NULL,
    remote_path VARCHAR(500) NOT NULL,
    file_type VARCHAR(100) NOT NULL,
    file_size BIGINT(20) UNSIGNED NOT NULL,
    mime_type VARCHAR(100),
    upload_time DATETIME DEFAULT CURRENT_TIMESTAMP,
    last_access DATETIME,
    access_count INT UNSIGNED DEFAULT 0,
    is_public TINYINT(1) DEFAULT 0,
    metadata TEXT,
    PRIMARY KEY (id),
    INDEX user_index (user_id),
    INDEX path_index (remote_path(255)),
    INDEX type_index (file_type),
    INDEX upload_time_index (upload_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

3.4 管理界面开发

创建用户友好的管理界面是系统成功的关键。我们可以使用WordPress的Admin API创建自定义管理页面:

<?php
/**
 * 文件管理界面
 */
class File_Management_UI {
    public function __construct() {
        add_action('admin_menu', [$this, 'add_admin_menu']);
        add_action('admin_enqueue_scripts', [$this, 'enqueue_scripts']);
    }
    
    public function add_admin_menu() {
        add_menu_page(
            '云文件管理',
            '云文件',
            'upload_files',
            'cloud-file-manager',
            [$this, 'render_main_page'],
            'dashicons-cloud',
            30
        );
        
        add_submenu_page(
            'cloud-file-manager',
            '上传文件',
            '上传',
            'upload_files',
            'cloud-file-upload',
            [$this, 'render_upload_page']
        );
        
        add_submenu_page(
            'cloud-file-manager',
            '文件统计',
            '统计',
            'manage_options',
            'cloud-file-stats',
            [$this, 'render_stats_page']
        );
    }
    
    public function render_main_page() {
        ?>
        <div class="wrap">
            <h1 class="wp-heading-inline">云文件管理</h1>
            <a href="<?php echo admin_url('admin.php?page=cloud-file-upload'); ?>" class="page-title-action">上传文件</a>
            <hr class="wp-header-end">
            
            <div id="cloud-file-manager">
                <!-- 文件列表将通过Vue.js动态加载 -->
                <div class="file-manager-container">
                    <div class="file-toolbar">
                        <div class="search-box">
                            <input type="search" id="file-search" placeholder="搜索文件...">
                        </div>
                        <div class="filter-options">
                            <select id="file-type-filter">
                                <option value="">所有类型</option>
                                <option value="image">图片</option>
                                <option value="document">文档</option>
                                <option value="video">视频</option>
                            </select>
                        </div>
                    </div>
                    
                    <div class="file-list-container">
                        <!-- 文件列表将通过AJAX加载 -->
                    </div>
                    
                    <div class="file-pagination">
                        <!-- 分页控件 -->
                    </div>
                </div>
            </div>
        </div>
        <?php
    }
    
    public function enqueue_scripts($hook) {
        if (strpos($hook, 'cloud-file') === false) {
            return;
        }
        
        wp_enqueue_style(
            'cloud-file-manager',
            plugins_url('css/file-manager.css', __FILE__),
            [],
            '1.0.0'
        );
        
        wp_enqueue_script(
            'cloud-file-manager',
            plugins_url('js/file-manager.js', __FILE__),
            ['jquery', 'vue'],
            '1.0.0',
            true
        );
        
        wp_localize_script('cloud-file-manager', 'cloudFileManager', [
            'ajax_url' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('cloud_file_manager'),
            'strings' => [
                'delete_confirm' => '确定要删除这个文件吗?',
                'upload_success' => '文件上传成功',
                'upload_failed' => '文件上传失败',
            ]
        ]);
    }
}

第四部分:基于文件系统的实用小工具开发

4.1 图片水印添加工具

<?php
/**
 * 图片水印工具
 */
class Image_Watermark_Tool {
    private $adapter;
    
    public function __construct($adapter) {
        $this->adapter = $adapter;
        add_action('wp_ajax_add_watermark', [$this, 'ajax_add_watermark']);
    }
    
    public function add_watermark($image_path, $watermark_text, $options = []) {
        // 从云存储下载图片
        $temp_path = $this->download_to_temp($image_path);
        
        // 获取图片信息
        $image_info = getimagesize($temp_path);
        $image_type = $image_info[2];
        
        // 根据图片类型创建图像资源
        switch ($image_type) {
            case IMAGETYPE_JPEG:
                $image = imagecreatefromjpeg($temp_path);
                break;
            case IMAGETYPE_PNG:
                $image = imagecreatefrompng($temp_path);
                break;
            case IMAGETYPE_GIF:
                $image = imagecreatefromgif($temp_path);
                break;
            default:
                return false;
        }
        
        // 设置水印颜色和字体
        $text_color = imagecolorallocatealpha($image, 255, 255, 255, 60);
        $font_size = isset($options['font_size']) ? $options['font_size'] : 20;
        $font_path = isset($options['font_path']) ? $options['font_path'] : '';
        
        // 计算水印位置
        $text_box = imagettfbbox($font_size, 0, $font_path, $watermark_text);
        $text_width = $text_box[2] - $text_box[0];
        $text_height = $text_box[7] - $text_box[1];
        
        $x = imagesx($image) - $text_width - 10;
        $y = imagesy($image) - $text_height - 10;
        
        // 添加水印
        imagettftext($image, $font_size, 0, $x, $y, $text_color, $font_path, $watermark_text);
        
        // 保存处理后的图片
        $watermarked_path = $this->get_watermarked_path($temp_path);
        
        switch ($image_type) {
            case IMAGETYPE_JPEG:
                imagejpeg($image, $watermarked_path, 90);
                break;
            case IMAGETYPE_PNG:
                imagepng($image, $watermarked_path, 9);
                break;
            case IMAGETYPE_GIF:
                imagegif($image, $watermarked_path);
                break;
        }
        
        imagedestroy($image);
        
        // 上传处理后的图片
        $new_remote_path = $this->get_watermarked_remote_path($image_path);
        $result = $this->adapter->upload($watermarked_path, $new_remote_path);
        
        // 清理临时文件
        unlink($temp_path);
        unlink($watermarked_path);
        
        return $result['success'] ? $new_remote_path : false;
    }
    
    public function ajax_add_watermark() {
        check_ajax_referer('watermark_tool', 'nonce');
        
        $file_id = intval($_POST['file_id']);
        $watermark_text = sanitize_text_field($_POST['watermark_text']);
        
        // 获取文件信息
        $file_info = $this->get_file_info($file_id);
        
        if (!$file_info || !$this->is_image($file_info['mime_type'])) {

4.2 文件批量处理工具

<?php
/**
 * 文件批量处理工具
 */
class Batch_File_Processor {
    private $adapter;
    private $batch_size = 50; // 每批处理文件数量
    
    public function __construct($adapter) {
        $this->adapter = $adapter;
        add_action('wp_ajax_batch_process_files', [$this, 'ajax_batch_process']);
    }
    
    public function process_batch($file_ids, $operation, $params = []) {
        $results = [
            'success' => [],
            'failed' => [],
            'total' => count($file_ids)
        ];
        
        // 分批处理,避免内存溢出
        $chunks = array_chunk($file_ids, $this->batch_size);
        
        foreach ($chunks as $chunk) {
            foreach ($chunk as $file_id) {
                try {
                    $result = $this->process_single_file($file_id, $operation, $params);
                    
                    if ($result['success']) {
                        $results['success'][] = [
                            'id' => $file_id,
                            'message' => $result['message']
                        ];
                    } else {
                        $results['failed'][] = [
                            'id' => $file_id,
                            'error' => $result['error']
                        ];
                    }
                    
                    // 短暂暂停,减轻服务器压力
                    usleep(100000); // 0.1秒
                    
                } catch (Exception $e) {
                    $results['failed'][] = [
                        'id' => $file_id,
                        'error' => $e->getMessage()
                    ];
                }
            }
        }
        
        return $results;
    }
    
    private function process_single_file($file_id, $operation, $params) {
        global $wpdb;
        
        // 获取文件信息
        $file = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}cloud_files WHERE id = %d",
            $file_id
        ));
        
        if (!$file) {
            return ['success' => false, 'error' => '文件不存在'];
        }
        
        switch ($operation) {
            case 'compress_images':
                return $this->compress_image($file, $params);
                
            case 'convert_format':
                return $this->convert_format($file, $params);
                
            case 'add_metadata':
                return $this->add_metadata($file, $params);
                
            case 'generate_thumbnails':
                return $this->generate_thumbnails($file, $params);
                
            case 'optimize_for_web':
                return $this->optimize_for_web($file, $params);
                
            default:
                return ['success' => false, 'error' => '不支持的操作'];
        }
    }
    
    private function compress_image($file, $params) {
        if (!$this->is_image($file->mime_type)) {
            return ['success' => false, 'error' => '不是图片文件'];
        }
        
        // 下载文件到临时目录
        $temp_path = $this->download_to_temp($file->remote_path);
        
        // 根据图片类型进行压缩
        $compressed_path = $this->compress_image_file($temp_path, $params);
        
        if (!$compressed_path) {
            unlink($temp_path);
            return ['success' => false, 'error' => '压缩失败'];
        }
        
        // 计算压缩率
        $original_size = filesize($temp_path);
        $compressed_size = filesize($compressed_path);
        $compression_rate = round((1 - $compressed_size / $original_size) * 100, 2);
        
        // 上传压缩后的文件
        $new_remote_path = $this->get_compressed_path($file->remote_path);
        $upload_result = $this->adapter->upload($compressed_path, $new_remote_path);
        
        // 清理临时文件
        unlink($temp_path);
        unlink($compressed_path);
        
        if ($upload_result['success']) {
            // 更新数据库记录
            $this->update_file_record($file->id, [
                'compressed_path' => $new_remote_path,
                'original_size' => $original_size,
                'compressed_size' => $compressed_size,
                'compression_rate' => $compression_rate
            ]);
            
            return [
                'success' => true,
                'message' => "压缩成功,压缩率:{$compression_rate}%"
            ];
        }
        
        return ['success' => false, 'error' => '上传压缩文件失败'];
    }
    
    private function compress_image_file($image_path, $params) {
        $quality = isset($params['quality']) ? $params['quality'] : 80;
        $max_width = isset($params['max_width']) ? $params['max_width'] : 1920;
        
        $image_info = getimagesize($image_path);
        $image_type = $image_info[2];
        
        // 创建图像资源
        switch ($image_type) {
            case IMAGETYPE_JPEG:
                $image = imagecreatefromjpeg($image_path);
                break;
            case IMAGETYPE_PNG:
                $image = imagecreatefrompng($image_path);
                // 保留透明度
                imagealphablending($image, false);
                imagesavealpha($image, true);
                break;
            default:
                return false;
        }
        
        // 调整尺寸
        $original_width = imagesx($image);
        $original_height = imagesy($image);
        
        if ($original_width > $max_width) {
            $new_width = $max_width;
            $new_height = intval($original_height * ($max_width / $original_width));
            
            $resized_image = imagecreatetruecolor($new_width, $new_height);
            
            // 处理PNG透明度
            if ($image_type == IMAGETYPE_PNG) {
                imagealphablending($resized_image, false);
                imagesavealpha($resized_image, true);
                $transparent = imagecolorallocatealpha($resized_image, 255, 255, 255, 127);
                imagefilledrectangle($resized_image, 0, 0, $new_width, $new_height, $transparent);
            }
            
            imagecopyresampled(
                $resized_image, $image,
                0, 0, 0, 0,
                $new_width, $new_height,
                $original_width, $original_height
            );
            
            imagedestroy($image);
            $image = $resized_image;
        }
        
        // 保存压缩后的图片
        $compressed_path = $this->get_temp_file_path('compressed_');
        
        switch ($image_type) {
            case IMAGETYPE_JPEG:
                imagejpeg($image, $compressed_path, $quality);
                break;
            case IMAGETYPE_PNG:
                // PNG质量参数是0-9,与JPEG相反
                $png_quality = 9 - round(($quality / 100) * 9);
                imagepng($image, $compressed_path, $png_quality);
                break;
        }
        
        imagedestroy($image);
        
        return $compressed_path;
    }
    
    public function ajax_batch_process() {
        check_ajax_referer('batch_processor', 'nonce');
        
        if (!current_user_can('upload_files')) {
            wp_send_json_error('权限不足');
        }
        
        $file_ids = array_map('intval', $_POST['file_ids']);
        $operation = sanitize_text_field($_POST['operation']);
        $params = isset($_POST['params']) ? $_POST['params'] : [];
        
        // 异步处理
        if (isset($_POST['async']) && $_POST['async']) {
            $this->start_async_batch_process($file_ids, $operation, $params);
            wp_send_json_success(['message' => '批量处理已开始']);
        } else {
            $results = $this->process_batch($file_ids, $operation, $params);
            wp_send_json_success($results);
        }
    }
    
    private function start_async_batch_process($file_ids, $operation, $params) {
        // 创建后台任务
        $task_id = wp_generate_uuid4();
        
        $task_data = [
            'file_ids' => $file_ids,
            'operation' => $operation,
            'params' => $params,
            'status' => 'pending',
            'progress' => 0,
            'created_at' => current_time('mysql'),
            'created_by' => get_current_user_id()
        ];
        
        // 保存任务到数据库
        $this->save_batch_task($task_id, $task_data);
        
        // 触发后台处理
        wp_schedule_single_event(time() + 5, 'process_batch_task', [$task_id]);
        
        return $task_id;
    }
}

4.3 智能文件分类器

<?php
/**
 * 智能文件分类器
 */
class Smart_File_Classifier {
    private $adapter;
    private $categories = [
        'images' => ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'],
        'documents' => ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt'],
        'videos' => ['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv'],
        'audio' => ['mp3', 'wav', 'ogg', 'm4a'],
        'archives' => ['zip', 'rar', '7z', 'tar', 'gz'],
        'code' => ['php', 'js', 'css', 'html', 'py', 'java', 'cpp']
    ];
    
    public function __construct($adapter) {
        $this->adapter = $adapter;
        add_action('wp_ajax_classify_files', [$this, 'ajax_classify_files']);
        add_action('add_attachment', [$this, 'auto_classify_new_file']);
    }
    
    public function classify_file($file_path, $file_name) {
        $extension = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
        
        // 根据扩展名分类
        foreach ($this->categories as $category => $extensions) {
            if (in_array($extension, $extensions)) {
                return $category;
            }
        }
        
        // 使用MIME类型进一步分类
        $mime_type = $this->get_mime_type($file_path);
        if ($mime_type) {
            return $this->classify_by_mime_type($mime_type);
        }
        
        return 'other';
    }
    
    private function classify_by_mime_type($mime_type) {
        $mime_categories = [
            'image/' => 'images',
            'application/pdf' => 'documents',
            'application/msword' => 'documents',
            'application/vnd.openxmlformats-officedocument' => 'documents',
            'video/' => 'videos',
            'audio/' => 'audio',
            'application/zip' => 'archives',
            'application/x-rar-compressed' => 'archives',
            'text/' => 'documents'
        ];
        
        foreach ($mime_categories as $prefix => $category) {
            if (strpos($mime_type, $prefix) === 0) {
                return $category;
            }
        }
        
        return 'other';
    }
    
    public function auto_classify_new_file($attachment_id) {
        $file_path = get_attached_file($attachment_id);
        $file_name = basename($file_path);
        
        $category = $this->classify_file($file_path, $file_name);
        
        // 保存分类信息
        update_post_meta($attachment_id, '_file_category', $category);
        
        // 如果是图片,提取更多信息
        if ($category === 'images') {
            $this->extract_image_metadata($attachment_id, $file_path);
        }
    }
    
    private function extract_image_metadata($attachment_id, $file_path) {
        $metadata = [];
        
        // 获取EXIF数据
        if (function_exists('exif_read_data') && in_array(strtolower(pathinfo($file_path, PATHINFO_EXTENSION)), ['jpg', 'jpeg'])) {
            $exif = @exif_read_data($file_path);
            if ($exif) {
                if (isset($exif['DateTimeOriginal'])) {
                    $metadata['taken_date'] = $exif['DateTimeOriginal'];
                }
                if (isset($exif['GPSLatitude']) && isset($exif['GPSLongitude'])) {
                    $metadata['gps'] = $this->convert_gps($exif['GPSLatitude'], $exif['GPSLongitude']);
                }
                if (isset($exif['Make'])) {
                    $metadata['camera_make'] = $exif['Make'];
                }
                if (isset($exif['Model'])) {
                    $metadata['camera_model'] = $exif['Model'];
                }
            }
        }
        
        // 获取图片尺寸
        $image_size = getimagesize($file_path);
        if ($image_size) {
            $metadata['dimensions'] = [
                'width' => $image_size[0],
                'height' => $image_size[1]
            ];
            $metadata['mime_type'] = $image_size['mime'];
        }
        
        // 计算文件哈希
        $metadata['file_hash'] = md5_file($file_path);
        
        // 保存元数据
        update_post_meta($attachment_id, '_image_metadata', $metadata);
    }
    
    private function convert_gps($gps_lat, $gps_lon) {
        // 将GPS坐标转换为十进制
        $lat_degrees = count($gps_lat) > 0 ? $this->gps_to_degrees($gps_lat) : 0;
        $lon_degrees = count($gps_lon) > 0 ? $this->gps_to_degrees($gps_lon) : 0;
        
        // 确定半球
        $lat_direction = ($gps_lat['GPSLatitudeRef'] == 'S') ? -1 : 1;
        $lon_direction = ($gps_lon['GPSLongitudeRef'] == 'W') ? -1 : 1;
        
        return [
            'lat' => $lat_degrees * $lat_direction,
            'lon' => $lon_degrees * $lon_direction
        ];
    }
    
    private function gps_to_degrees($gps_coordinate) {
        $degrees = count($gps_coordinate) > 0 ? $this->gps_coordinate_to_number($gps_coordinate[0]) : 0;
        $minutes = count($gps_coordinate) > 1 ? $this->gps_coordinate_to_number($gps_coordinate[1]) : 0;
        $seconds = count($gps_coordinate) > 2 ? $this->gps_coordinate_to_number($gps_coordinate[2]) : 0;
        
        return $degrees + ($minutes / 60) + ($seconds / 3600);
    }
    
    private function gps_coordinate_to_number($coordinate_part) {
        $parts = explode('/', $coordinate_part);
        if (count($parts) <= 0) {
            return 0;
        }
        if (count($parts) == 1) {
            return $parts[0];
        }
        return floatval($parts[0]) / floatval($parts[1]);
    }
    
    public function ajax_classify_files() {
        check_ajax_referer('file_classifier', 'nonce');
        
        $file_ids = array_map('intval', $_POST['file_ids']);
        $results = [];
        
        foreach ($file_ids as $file_id) {
            $file = get_post($file_id);
            if (!$file || $file->post_type != 'attachment') {
                continue;
            }
            
            $file_path = get_attached_file($file_id);
            $category = $this->classify_file($file_path, $file->post_title);
            
            // 更新分类
            update_post_meta($file_id, '_file_category', $category);
            
            $results[] = [
                'id' => $file_id,
                'name' => $file->post_title,
                'category' => $category,
                'icon' => $this->get_category_icon($category)
            ];
        }
        
        wp_send_json_success([
            'results' => $results,
            'total' => count($results)
        ]);
    }
    
    private function get_category_icon($category) {
        $icons = [
            'images' => 'dashicons-format-image',
            'documents' => 'dashicons-media-document',
            'videos' => 'dashicons-format-video',
            'audio' => 'dashicons-format-audio',
            'archives' => 'dashicons-media-archive',
            'code' => 'dashicons-editor-code',
            'other' => 'dashicons-media-default'
        ];
        
        return isset($icons[$category]) ? $icons[$category] : $icons['other'];
    }
}

4.4 文件分享与协作工具

<?php
/**
 * 文件分享与协作工具
 */
class File_Sharing_Tool {
    private $adapter;
    private $share_expiry_days = 7;
    
    public function __construct($adapter) {
        $this->adapter = $adapter;
        add_action('wp_ajax_create_file_share', [$this, 'ajax_create_share']);
        add_action('wp_ajax_revoke_file_share', [$this, 'ajax_revoke_share']);
        add_action('wp', [$this, 'handle_shared_file_access']);
    }
    
    public function create_share_link($file_id, $options = []) {
        global $wpdb;
        
        // 验证文件存在且用户有权限
        $file = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}cloud_files WHERE id = %d",
            $file_id
        ));
        
        if (!$file) {
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5076.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

工作时间:周一至周五,9:00-17:30,节假日休息
返回顶部