dootask/app/Tasks/DeleteTmpTask.php
kuaifan 184fb27680 feat(upload): 分片上传统一链路,5 场景突破单文件 1G 限制
- 新增 api/upload/{init,chunk,merge} 入口与 ChunkUpload 模块(5MB 分片、3 并发、Redis 状态机)
- 5 场景接入:文件柜 / 聊天 / 任务附件 / 头像&系统图片 / 编辑器粘贴
- 秒传:同用户同 hash 复用 FileContent 物理文件,零传输
- 续传:Redis + localStorage 双索引,24h TTL
- 与老接口对齐:pid 锁、≤300 上限、webkit_relative_path 目录递归、overwrite 替换语义
- init 阶段读 file_upload_limit 拦截超限,避免传完分片才报错
- DeleteTmpTask 加 tmp_chunks case 兜底清理 24h 未合并目录
- files 表新增 hash 列(migration)
- 前端 chunkedUpload wrapper:主线程 spark-md5 流式 + 指数退避重试
- ai-kb 同步:upload / file-upload-limit / upload-size-limit 三个 chunk
2026-06-30 04:30:09 +00:00

147 lines
4.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Tasks;
use App\Models\File;
use App\Models\TaskWorker;
use App\Models\Tmp;
use App\Models\UserDevice;
use App\Models\UmengLog;
use App\Models\WebSocketTmpMsg;
use App\Module\Base;
use Carbon\Carbon;
/**
* 删除过期临时数据任务
* Class DeleteTmpTask
* @package App\Tasks
*/
class DeleteTmpTask extends AbstractTask
{
protected $data;
protected $hours; // 多久后删除,单位小时
/**
* @param string $data
* @param int $hours
*/
public function __construct(string $data, int $hours = 24)
{
parent::__construct(...func_get_args());
$this->data = $data;
$this->hours = $hours;
}
public function start()
{
switch ($this->data) {
case 'tmp_msgs':
WebSocketTmpMsg::where('created_at', '<', Carbon::now()->subHours($this->hours))
->orderBy('id')
->chunk(500, function ($msgs) {
/** @var WebSocketTmpMsg $msg */
foreach ($msgs as $msg) {
$msg->delete();
}
});
break;
case 'tmp':
Tmp::where('created_at', '<', Carbon::now()->subHours($this->hours))
->orderBy('id')
->chunk(500, function ($tmps) {
/** @var Tmp $tmp */
foreach ($tmps as $tmp) {
$tmp->delete();
}
});
break;
case 'task_worker':
TaskWorker::onlyTrashed()
->where('deleted_at', '<', Carbon::now()->subHours($this->hours))
->orderBy('id')
->forceDelete();
break;
case 'file':
$day = intval(config('dootask.auto_empty_file_recycle'));
if ($day <= 0) {
return;
}
File::onlyTrashed()
->where('deleted_at', '<', Carbon::now()->subHours($day))
->orderBy('id')
->chunk(500, function ($files) {
/** @var File $file */
foreach ($files as $file) {
$file->forceDeleteFile();
}
});
break;
case 'tmp_file':
$day = intval(config('dootask.auto_empty_temp_file'));
if ($day <= 0) {
return;
}
$files = Base::recursiveFiles(public_path('uploads/tmp'));
foreach ($files as $file) {
$time = @filemtime($file);
if ($time && $time < time() - 3600 * 24 * $day) {
unlink($file);
}
}
break;
case 'tmp_chunks':
// 分片上传残留upload_id 目录超过 hours 小时未合并则整目录清掉
$chunksRoot = public_path('uploads/tmp/chunks');
if (!is_dir($chunksRoot)) {
break;
}
$cutoff = time() - 3600 * $this->hours;
foreach (glob($chunksRoot . '/*', GLOB_ONLYDIR) ?: [] as $userDir) {
foreach (glob($userDir . '/*', GLOB_ONLYDIR) ?: [] as $uploadDir) {
$mtime = @filemtime($uploadDir);
if ($mtime && $mtime < $cutoff) {
Base::deleteDirAndFile($uploadDir);
}
}
// 顺手清理空 user 目录
if (count(scandir($userDir) ?: []) <= 2) {
@rmdir($userDir);
}
}
break;
case 'user_device':
UserDevice::where('expired_at', '<', Carbon::now()->subHours($this->hours))
->orderBy('id')
->chunk(500, function ($devices) {
/** @var UserDevice $device */
foreach ($devices as $device) {
UserDevice::forget($device);
}
});
break;
case 'umeng_log':
UmengLog::where('created_at', '<', Carbon::now()->subHours($this->hours))
->orderBy('id')
->chunk(500, function ($logs) {
/** @var UmengLog $log */
foreach ($logs as $log) {
$log->delete();
}
});
break;
}
}
public function end()
{
}
}