智慧教务系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

11 KiB

后端文件上传封装方法文档

概述

本项目使用了完整的文件上传架构,支持多种存储方式(本地、阿里云OSS、腾讯云COS、七牛云等),并提供了完善的文件管理功能。

核心架构

1. 服务类层次结构

UploadService (API层)
    ↓
CoreUploadService (核心业务层)
    ↓
CoreFileService (基础文件服务层)
    ↓
UploadLoader (存储引擎加载器)

2. 主要组件

  • UploadService: API层上传服务,处理前端请求
  • CoreUploadService: 核心上传业务逻辑
  • CoreFileService: 基础文件操作服务
  • CoreImageService: 图片处理服务(缩略图等)
  • FileDict: 文件类型字典定义

API接口使用方法

1. 图片上传接口

接口地址: POST /api/upload/image

请求参数:

  • file: 上传的图片文件

响应示例:

{
    "code": 1,
    "msg": "SUCCESS",
    "data": {
        "url": "https://example.com/upload/file/image/202501/31/1738309123456.jpg",
        "ext": "jpg",
        "name": "1738309123456.jpg",
        "att_id": 123
    }
}

使用示例 (curl):

curl -X POST http://localhost:20080/api/upload/image \
  -H "Content-Type: multipart/form-data" \
  -H "token: your_token_here" \  
  -F "file=@/path/to/image.jpg"

2. 头像上传接口(无token验证)

接口地址: POST /api/upload/avatar

特点:

  • 无需token验证
  • 专门用于头像上传
  • 存储路径: file/avatar/年月/日/

3. 视频上传接口

接口地址: POST /api/upload/video

请求参数:

  • file: 上传的视频文件

4. 文档上传接口

接口地址: POST /api/upload/document

请求参数:

  • file: 上传的文档文件
  • type: 文档类型(必填),支持的类型见FileDict::getSceneType()

服务类使用方法

1. 在业务代码中使用UploadService

<?php
use app\service\api\upload\UploadService;

class YourController
{
    public function uploadExample()
    {
        $uploadService = new UploadService();
        
        // 上传图片
        $result = $uploadService->image($_FILES['file']);
        
        // 结果包含:
        // $result['url'] - 文件访问URL
        // $result['att_id'] - 附件ID(如果启用了附件管理)
        
        return success($result);
    }
}

2. 使用CoreUploadService(更底层的控制)

<?php
use app\service\core\upload\CoreUploadService;
use app\dict\sys\FileDict;
use app\dict\sys\StorageDict;

class YourService
{
    public function customUpload($file)
    {
        $coreUploadService = new CoreUploadService(true); // true表示写入附件表
        
        // 自定义上传目录和类型
        $result = $coreUploadService->image(
            $file,                    // 文件
            'custom/path/image',      // 自定义目录
            0,                        // 分类ID
            StorageDict::LOCAL        // 指定存储类型
        );
        
        return $result;
    }
}

存储配置

1. 存储类型

项目支持以下存储类型:

  • local: 本地存储
  • aliyun: 阿里云OSS
  • qcloud: 腾讯云COS
  • qiniu: 七牛云

2. 文件类型

支持的文件场景类型(FileDict::getSceneType()):

  • wechat: 微信相关文件
  • aliyun: 阿里云相关文件
  • image: 图片文件
  • video: 视频文件
  • applet: 小程序包
  • excel: Excel文件

文件路径和URL处理

1. 路径生成规则

// 图片上传路径示例:
// file/image/202501/31/randomname.jpg
$dir = $this->root_path . '/' . 'image' . '/' . date('Ym') . '/' . date('d');

// 头像上传路径示例:
// file/avatar/202501/31/randomname.jpg
$dir = $this->root_path . '/' . 'avatar' . '/' . date('Ym') . '/' . date('d');

2. URL转换函数

重要: 项目中使用的URL转换函数

// 在common.php中定义的函数
function get_file_url(string $path): string
{
    if (!$path) return '';
    if (!str_contains($path, 'http://') && !str_contains($path, 'https://')) {
        return request()->domain() . '/' . path_to_url($path);
    } else {
        return path_to_url($path);
    }
}

// 注意:项目中使用了get_image_url()函数,但在common.php中未找到定义
// 建议在common.php中添加以下函数作为别名:
function get_image_url(string $path): string
{
    return get_file_url($path);
}

3. 路径转换辅助函数

// 路径转URL
function path_to_url($path): string
{
    return trim(str_replace(DIRECTORY_SEPARATOR, '/', $path), '.');
}

// URL转路径
function url_to_path($url): string
{
    if (str_contains($url, 'http://') || str_contains($url, 'https://')) {
        return $url; // 网络图片不转换
    }
    return public_path() . trim(str_replace('/', DIRECTORY_SEPARATOR, $url));
}

图片处理功能

1. 缩略图生成

use app\service\core\upload\CoreImageService;

$imageService = new CoreImageService();

// 生成缩略图
$thumbs = $imageService->thumb($imagePath, 'all', false);

// 或使用全局函数
$thumbs = get_thumb_images($imagePath, 'big', false);

2. 缩略图规格

支持的缩略图类型(FileDict::getThumbType()):

  • big: 大图
  • mid: 中图
  • small: 小图

文件验证和配置

1. 设置上传验证规则

$coreFileService = new CoreFileService();

$coreFileService->setValidate([
    'ext' => ['jpg', 'jpeg', 'png', 'gif'], // 允许的扩展名
    'mime' => ['image/jpeg', 'image/png'],  // 允许的MIME类型
    'size' => 2 * 1024 * 1024              // 文件大小限制(字节)
]);

2. 设置上传目录

$coreFileService->setRootPath('custom_upload_dir');

完整使用示例

1. 在控制器中处理文件上传

<?php
namespace app\api\controller\example;

use core\base\BaseApiController;
use app\service\api\upload\UploadService;

class FileController extends BaseApiController
{
    /**
     * 自定义文件上传
     */
    public function uploadFile()
    {
        $data = $this->request->params([
            ['file', 'file'],
            ['type', 'image'] // 文件类型
        ]);
        
        $uploadService = new UploadService();
        
        try {
            // 根据类型选择上传方法
            switch ($data['type']) {
                case 'image':
                    $result = $uploadService->image($data['file']);
                    break;
                case 'video':
                    $result = $uploadService->video($data['file']);
                    break;
                case 'document':
                    $result = $uploadService->document($data['file'], 'excel');
                    break;
                default:
                    return fail('不支持的文件类型');
            }
            
            // 添加额外信息
            $result['ext'] = pathinfo($result['url'], PATHINFO_EXTENSION);
            $result['name'] = basename($result['url']);
            
            return success($result);
            
        } catch (\Exception $e) {
            return fail($e->getMessage());
        }
    }
}

2. 在服务类中批量处理文件

<?php
namespace app\service\api\example;

use app\service\core\upload\CoreUploadService;
use core\base\BaseService;

class DocumentService extends BaseService
{
    /**
     * 批量上传文件并保存记录
     */
    public function batchUploadDocuments(array $files, int $relatedId)
    {
        $uploadService = new CoreUploadService(true); // 启用附件管理
        $results = [];
        
        foreach ($files as $file) {
            try {
                $result = $uploadService->document(
                    $file,
                    'document',
                    'documents/' . date('Y/m/d'),
                    'local'
                );
                
                // 保存文件记录到业务表
                $this->saveFileRecord($result, $relatedId);
                
                $results[] = $result;
                
            } catch (\Exception $e) {
                // 记录错误但继续处理其他文件
                \think\facade\Log::error('文件上传失败: ' . $e->getMessage());
            }
        }
        
        return $results;
    }
    
    private function saveFileRecord($uploadResult, $relatedId)
    {
        // 将上传结果保存到业务表的逻辑
        // ...
    }
}

注意事项

  1. 函数缺失问题: 项目中使用了get_image_url()函数,但在common.php中未定义,建议添加以下代码:
// 添加到 common.php 文件中
if (!function_exists('get_image_url')) {
    function get_image_url(string $path): string
    {
        return get_file_url($path);
    }
}
  1. token验证: 除头像上传接口外,其他上传接口都需要有效的token

  2. 文件大小限制: 根据PHP配置和业务需求设置合理的文件大小限制

  3. 存储空间: 定期清理无用文件,避免存储空间不足

  4. 安全考虑:

    • 验证文件类型和扩展名
    • 限制上传文件大小
    • 对上传的文件进行安全检查

错误处理

常见错误及解决方案:

  1. 上传失败: 检查文件大小、类型是否符合要求
  2. 存储配置错误: 检查存储服务配置是否正确
  3. 权限问题: 确保上传目录有写入权限
  4. token失效: 重新获取有效token

测试和验证

1. 登录获取Token

首先需要获取有效的token:

# 员工端登录
curl -X POST "http://localhost:20080/api/login/unified" \
  -H "Content-Type: application/json" \
  -d '{"username": "19218917377", "password": "19218917377", "login_type": "staff"}'

2. 测试文件上传

使用以下curl命令测试上传功能:

# 测试员工端图片上传
curl -X POST http://localhost:20080/api/uploadImage \
  -H "token: your_valid_token_here" \
  -F "file=@/path/to/image.jpg"

# 测试学生端图片上传  
curl -X POST http://localhost:20080/api/memberUploadImage \
  -H "token: your_valid_token_here" \
  -F "file=@/path/to/image.jpg"

成功响应示例:

{
    "code": 1,
    "msg": "操作成功",
    "data": {
        "url": "https://damai-1345293182.cos.ap-guangzhou.myqcloud.com/upload/file/image/202507/31/1753969912ae14e3ced3c300ff02b7da3688eff61a_tencent.png",
        "ext": "png",
        "name": "1753969912ae14e3ced3c300ff02b7da3688eff61a_tencent.png"
    }
}

失败响应示例:

{
    "code": 0,
    "msg": "登录过期,请重新登录",
    "data": []
}

3. 验证get_image_url函数

验证体测服务中的文件URL处理:

# 获体测报告列表,验证get_image_url函数处理PDF文件路径
curl -X GET "http://localhost:20080/api/xy/physicalTest?student_id=1&page=1&limit=10" \
  -H "token: your_valid_token_here"

扩展功能

  1. 添加新的存储类型: 实现对应的存储驱动类
  2. 自定义文件处理: 继承CoreUploadService并重写相关方法
  3. 文件水印: 在图片上传后添加水印处理
  4. 文件压缩: 对上传的图片进行自动压缩

文档最后更新时间: 2025-01-31