在 Webman 项目中,通过 multipart/form-data 上传文件时,Workerman 会将上传文件写入临时目录。
测试发现:当完整 HTTP 请求包长度超过 2048 字节时,请求处理结束后不会自动调用 $request->destroy(),导致未被业务逻辑移动或删除的上传临时文件持续保留在临时目录中。
其中,2048 字节是 Workerman TcpConnection::MAX_CACHE_STRING_LENGTH 的请求缓存阈值,判断对象是完整 HTTP 请求原始数据长度,并非单纯的上传文件大小。
对于请求包长度不超过 2048 字节的单请求,Workerman 在回调结束后会调用 destroy();但当请求超过该阈值时,请求不会进入该缓存分支,onMessage 返回后也没有对应的 destroy() 清理逻辑。
Request::destroy() 会删除上传文件信息中 tmp_name 对应的临时文件。因此,未执行该方法可能导致上传临时目录持续堆积文件。
use Workerman\Protocols\Http;
Http::uploadTmpDir(runtime_path('upload-tmp'));
multipart/form-data 的 POST 请求,同时携带普通请求参数和上传文件。$file->move(),或不主动删除上传临时文件。runtime/upload-tmp 目录。上传临时文件仍然存在,未被自动清理。
Workerman 在 TcpConnection 中对完整请求包长度不超过 MAX_CACHE_STRING_LENGTH(2048)的请求进入缓存分支,并在执行完 onMessage 后调用:
$request->destroy();
当请求包长度超过 2048 字节时,不会进入该缓存分支;请求执行完 onMessage 后没有对应的 destroy() 调用。
通过继承并重载 Webman 的 App 类,在每次请求处理结束后统一调用 destroy():
<?php
namespace app\admin\process;
use Webman\App;
use Workerman\Protocols\Http\Request as WorkermanRequest;
/**
* 自定义 HTTP 应用,确保请求结束后清理上传临时文件。
*/
class Http extends App
{
/**
* 请求结束后清理 Workerman 上传临时文件。
*
* @param mixed $connection
* @param mixed $request
* @return null
*/
public function onMessage($connection, $request)
{
try {
return parent::onMessage($connection, $request);
} finally {
if ($request instanceof WorkermanRequest) {
$request->destroy();
}
}
}
}
并在 config/process.php 中使用自定义的 HTTP 应用类。
>= 8.1workerman/webman-framework:^2.1workerman/workerman:>= 5.1
这个现象只在 5.1.0 到 5.1.4 上成立。
你装的不是最新版。这个问题在 Workerman 5.1.5 已经修好了,请升级到 5.1.5 或更高版本(当前是 5.2.3)
好的