You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 10下如何验证上传Excel为官网下载的原文件?

可行方案及实现思路(Laravel 10)

针对你需求的核心——确保上传文件是官网下发的原模板,以下是几个落地性强的方案,结合Laravel的加密、Excel处理能力实现:

方案一:隐藏工作表存储加密令牌(推荐)

利用Excel支持隐藏工作表的特性,在模板文件中新增一个用户不可见的工作表,存储加密后的唯一令牌,上传时读取该令牌解密校验。用户几乎不会主动修改隐藏工作表,安全性较高。

实现步骤

  1. 生成带隐藏校验表的模板文件
    借助maatwebsite/laravel-excel包(Laravel常用Excel处理工具)生成模板,新增隐藏工作表存储加密令牌:

    use Maatwebsite\Excel\Facades\Excel;
    use Illuminate\Support\Str;
    use Illuminate\Encryption\Encrypter;
    use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
    
    // 生成唯一UUID令牌并加密
    $token = Crypt::encryptString(Str::uuid());
    
    // 生成带隐藏校验表的Excel模板
    Excel::store(new class($token) implements FromCollection, WithSheets, WithEvents {
        private $token;
    
        public function __construct($token)
        {
            $this->token = $token;
        }
    
        // 主工作表(用户填写数据的模板)
        public function collection()
        {
            return collect([
                ['姓名', '邮箱', '手机号'], // 自定义校验规则的表头
                ['示例:张三', '示例:test@xxx.com', '示例:138xxxxxxx']
            ]);
        }
    
        // 定义多个工作表
        public function sheets(): array
        {
            return [
                '数据填写模板' => $this,
                '_verify' => new class($this->token) implements FromCollection {
                    private $token;
    
                    public function __construct($token)
                    {
                        $this->token = $token;
                    }
    
                    public function collection()
                    {
                        return collect([[$this->token]]); // 令牌存A1单元格
                    }
                }
            ];
        }
    
        // 隐藏校验工作表
        public function registerEvents(): array
        {
            return [
                AfterSheet::class => function(AfterSheet $event) {
                    $event->sheet->getDelegate()->getParent()
                        ->getSheetByName('_verify')
                        ->setSheetState(Worksheet::SHEETSTATE_HIDDEN);
                }
            ];
        }
    }, 'official_template.xlsx');
    
  2. 上传时校验令牌
    读取上传文件的隐藏工作表内容,解密后验证合法性:

    use Maatwebsite\Excel\Facades\Excel;
    
    $uploadedFile = $request->file('excel_file');
    
    try {
        // 读取隐藏工作表的令牌
        $verifyData = Excel::toArray(new class {
            public function collection(array $rows)
            {
                return $rows[0][0] ?? null;
            }
        }, $uploadedFile)->get('_verify');
        $encryptedToken = $verifyData[0][0] ?? '';
    
        // 解密令牌并验证格式
        $decryptedToken = Crypt::decryptString($encryptedToken);
        if (!Str::isUuid($decryptedToken)) {
            throw new \Exception('令牌格式无效');
        }
    
        // 可选:如果需要绑定用户,可将令牌存入数据库,上传时校验是否属于当前用户
        // $isValid = DB::table('template_tokens')->where(['user_id' => auth()->id(), 'token' => $decryptedToken])->exists();
        // if (!$isValid) throw new \Exception('非当前用户下载的模板');
    
    } catch (\Exception $e) {
        return back()->withErrors('文件无效,请使用官网下载的模板');
    }
    
    // 校验通过,处理用户填写的数据
    $userData = Excel::toArray(new class {
        public function collection(array $rows)
        {
            return array_slice($rows, 1); // 跳过表头和示例行
        }
    }, $uploadedFile)->get('数据填写模板');
    

方案二:自定义文档属性存储令牌

利用Excel的自定义文档属性功能,将加密令牌存入文件属性中,上传时读取该属性校验。

实现步骤

  1. 生成带自定义属性的模板

    use PhpOffice\PhpSpreadsheet\Spreadsheet;
    use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
    
    $spreadsheet = new Spreadsheet();
    $sheet = $spreadsheet->getActiveSheet();
    // 设置主工作表内容(表头、示例等)
    $sheet->setCellValue('A1', '姓名')->setCellValue('B1', '邮箱')->setCellValue('C1', '手机号');
    
    // 添加加密令牌到自定义属性
    $properties = $spreadsheet->getProperties();
    $properties->setCustomProperty('official_verify_token', Crypt::encryptString(Str::uuid()));
    
    $writer = new Xlsx($spreadsheet);
    $writer->save('official_template.xlsx');
    
  2. 上传时校验属性

    use PhpOffice\PhpSpreadsheet\IOFactory;
    
    $uploadedFile = $request->file('excel_file');
    $spreadsheet = IOFactory::load($uploadedFile->getPathname());
    $properties = $spreadsheet->getProperties();
    $encryptedToken = $properties->getCustomProperty('official_verify_token');
    
    if (!$encryptedToken) {
        return back()->withErrors('文件无效');
    }
    
    try {
        $decryptedToken = Crypt::decryptString($encryptedToken);
        if (!Str::isUuid($decryptedToken)) {
            throw new \Exception('令牌无效');
        }
    } catch (\Exception $e) {
        return back()->withErrors('文件无效,请使用官网下载的模板');
    }
    

方案三:哈希校验结合结构验证

如果不需要绑定用户,可预先计算模板文件的哈希值(排除用户填写区域),上传时校验文件结构(工作表数量、表头、格式)+ 核心区域哈希。但注意用户填写数据后文件哈希会变化,因此仅适合校验模板的原始结构。

核心思路

  • 预先存储模板的表头哈希、工作表数量等特征值
  • 上传时读取文件的表头,计算哈希后与存储值比对
  • 结合令牌方案使用,双重验证提升安全性

内容的提问来源于stack exchange,提问作者kamel dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 06:03:30