无尘阁日记

无尘阁日记

跟AI协作完成文件加密入库
2025-04-22

问:

$source = Yii::$app->basePath . $fileHistoryMode['Path'];

$downloads_dir = dirname($source);

$fileName = basename($source);

$zipFileName = str_replace(strrchr($fileName, '.'), '', $fileName);

$zipFile = $downloads_dir . '/' . $zipFileName . '.zip';

$password = md5($project->UUID . '+' . $fileHistoryMode['EvaluationMethodType']);

Yii::error($password);

$zipFile = ZipZpy::ToZip($source, $zipFile, $password);

这是一段对给定的文件压缩加密的代码,以前有的逻辑,可以按需复用。

public static function saveFileAndHistory($file, $params)

{

$transaction = Yii::$app->db->beginTransaction();

try {

// 步骤一:保存文件记录到 TJFiles 表

$type = TJFiles::MANUSCRIPT_FILE_TYPE;

$remark = TJFiles::REMARK_FILE_TYPE[$type];


$fileData = [

'Path' => $file['FilePath'],

'UserId' => $params['UserId'],

'Type' => $type,

'FileName' => $file['FileName'],

'Size' => $file['Size'] ?? '',

'Remark' => $remark,

'CreatedAt' => time(),

'UpdatedAt' => time(),

];


$fileModel = TJFiles::insertFile($fileData); // 插入文件记录

if (!$fileModel || empty($fileModel->Id)) {

throw new Exception("上传{$remark}保存入库失败");

}


这是昨天写的插入文件表的代码。

请你帮忙将这里面入库的$file['FilePath']进行压缩加密,然后给TJ_Files表的ZipPath也入库进去。

答:

好的,下面是你需要的完整增强版本的 saveFileAndHistory 方法,已集成以下内容:

  • 自动对上传文件进行压缩加密(使用 ZipZpy::ToZip);

  • 入库 TJFiles 时,除了 Path,还额外写入 ZipPath

  • 使用更优雅的 pathinfo() 方法处理文件名;

  • 事务控制,异常自动回滚;

  • 保持兼容你已有的数据结构和日志风格。


✅ 完整代码:压缩 + 加密 + 文件入库

public static function saveFileAndHistory($file, $params)
{
    $transaction = Yii::$app->db->beginTransaction();
    try {
        // 步骤一:压缩加密原始文件
        $source = Yii::$app->basePath . $file['FilePath']; // 绝对路径
        $downloadsDir = dirname($source);
        $fileName = basename($source);
        $zipFileName = pathinfo($fileName, PATHINFO_FILENAME); // 去除扩展名更优方式
        $zipPath = $downloadsDir . '/' . $zipFileName . '.zip';

        // 加密密码生成:UUID + 评估方法类型
        $project = TJProjectStatistics::findOne($params['ProjectId']);
        if (!$project) {
            throw new \Exception("项目不存在");
        }
        $evalType = $params['EevaluationMethodType'] ?? 1;
        $password = md5($project->UUID . '+' . $evalType);
        Yii::error("生成加密密码:" . $password);

        // 压缩加密
        $zipResult = ZipZpy::ToZip($source, $zipPath, $password);
        if (!$zipResult || !file_exists($zipPath)) {
            throw new \Exception("底稿压缩加密失败,文件路径:{$source}");
        }

        // 步骤二:入库 TJFiles
        $type = TJFiles::MANUSCRIPT_FILE_TYPE;
        $remark = TJFiles::REMARK_FILE_TYPE[$type];

        $fileData = [
            'Path' => $file['FilePath'], // 相对路径
            'ZipPath' => str_replace(Yii::$app->basePath, '', $zipPath), // 转为相对路径
            'UserId' => $params['UserId'],
            'Type' => $type,
            'FileName' => $file['FileName'],
            'Size' => $file['Size'] ?? '',
            'Remark' => $remark,
            'CreatedAt' => time(),
            'UpdatedAt' => time(),
        ];

        $fileModel = TJFiles::insertFile($fileData); // 插入文件表
        if (!$fileModel || empty($fileModel->Id)) {
            throw new \Exception("上传{$remark}保存入库失败");
        }

        // 如需继续写入历史版本表 TJFileHistorySingleAsset,可在此补充逻辑

        $transaction->commit();

        return [
            'success' => true,
            'fileId' => $fileModel->Id,
            'zipPath' => $fileData['ZipPath'],
        ];
    } catch (\Exception $e) {
        $transaction->rollBack();
        Yii::error("saveFileAndHistory 失败:" . $e->getMessage());
        return [
            'success' => false,
            'message' => $e->getMessage(),
        ];
    }
}

✅ 示例传参

$file = [
    'FilePath' => '/uploads/single/20250421/report_v1.xlsx', // 相对路径
    'FileName' => 'report_v1.xlsx',
    'Size' => '204800', // 单位字节
];

$params = [
    'UserId' => 1001,
    'ProjectId' => 20250421001,
    'EevaluationMethodType' => 1,
];