Skip to content

容器文件管理 API

本文档说明容器文件管理相关 API 的职责、调用凭据、访问模式和请求/响应参数。文件管理能力主要服务于应用详情文件页、Codeblitz 编辑器、微应用文件弹窗、压缩解压、权限修改、挂载文件编辑和分片上传。

整体使用方式

容器文件接口用于把面板文件管理能力映射到目标容器 rootfs。开发时先定位目标容器 PID,拿到后端返回的 WebDAV、压缩、权限 URL 和 webdavToken,再按文件操作类型调用对应接口。

基本流程

  1. 使用用户 token 调用 /panel-api/v1/pid,传入 namespace、节点 IP、Pod/容器信息。
  2. 后端返回 pidsubPidwebdavUrlwebdavBasePathcompressUrlpermissionUrlwebdavToken
  3. WebDAV 读写、压缩解压、权限修改使用返回的 URL 和 Authorization: Bearer {webdavToken}
  4. Codeblitz 编辑器通过 query 参数接收 api-urlapi-base-pathapi-token
  5. 挂载文件、分片上传、下载复制等场景按各自接口处理,不要手动拼生产代理路径。

场景选择

场景使用接口说明
定位容器 rootfs/panel-api/v1/pid返回文件访问所需 URL 和 token
目录和文件读写WebDAV PROPFINDGETPUTDELETE保持 WebDAV 协议响应
压缩解压compressUrl/compress/extract对容器内路径操作
修改权限permissionUrl/chmod/chown修改容器内文件权限
大文件上传分片上传接口上传、检查、合并分片
挂载文件编辑mount file 接口管理 ConfigMap/Secret 挂载内容

使用边界

  • webdavToken 当前来自 /pid 返回字段,本质上是当前请求上下文里的 token。
  • WebDAV 标准方法必须保留 XML、文件流等协议响应,不要包装为普通 JSON。
  • LOCAL_MOCK=true 只改变 rootfs 定位路径,不代表跳过用户认证。
  • /proc/sys/dev、socket、fifo、device 等特殊文件需要按文档限制处理。
  • 生产模式 URL 可能带 Agent 代理前缀,前端应使用后端返回的 URL。

通用说明

鉴权

GET /panel-api/v1/files/webdav-test/*path 外,本文接口均需要用户 token:

http
Authorization: Bearer <token>

/panel-api/v1/pid 返回的 webdavToken 当前就是用户 token。前端和 Codeblitz 访问 WebDAV、压缩、权限接口时,应使用:

http
Authorization: Bearer <webdavToken>

LOCAL_MOCK=true 只改变文件系统定位方式,不跳过用户认证。

响应格式

当前后端成功响应处理器直接返回业务对象,不额外包裹 codedatamessage。WebDAV 接口必须保持 WebDAV 标准响应,PROPFIND 返回 XML,GET 返回文件流,不能改成普通 JSON。

错误响应通常由框架统一处理;显式校验错误常见 HTTP 状态码为 400,服务端错误为 500,下载文件不存在为 404

参数位置

/panel-api/v1/pid 主要使用 query/form 参数。WebDAV 接口通过 path 表示目标 PID 和容器内路径,Header 承载 DepthDestinationOverwrite 等协议参数,PUT body 为文件内容。压缩、权限、分片上传和挂载文件接口按各自参数表使用 JSON body、form 或 multipart。

能力概览

能力说明
定位容器文件系统通过 /panel-api/v1/pid 获取目标容器的 pidsubPidwebdavUrlcompressUrlpermissionUrlwebdavToken
WebDAV 文件访问使用标准 WebDAV 方法读取、写入、删除、移动、复制和列目录
压缩解压对容器内路径执行 zip、tar、tar.gz、tar.xz 等压缩,支持多种格式解压
权限修改对容器内文件执行 chmod、chown
文件下载和复制通过 /download/*path/cp/cppid/mvpid 复制或下载文件
分片上传面板侧分片上传、检查和合并,可直接合并到目标容器
挂载文件查询、创建、更新、删除和修改 ConfigMap/Secret 挂载文件

调用流程

  1. 前端使用用户 token 调用 /panel-api/v1/pid,传入 namespaceHostIppodNamecontainerNamecontainerId
  2. 后端返回 webdavUrlwebdavBasePathcompressUrlpermissionUrlwebdavToken
  3. 前端或 Codeblitz 使用 webdavToken 访问 WebDAV、压缩和权限接口。
  4. 需要生产 Agent 代理时,前端使用后端返回的 URL,不自行拼接生产代理路径。

LOCAL_MOCK 路径差异

文件接口最终都会映射到目标进程 rootfs:

模式rootfs 基础路径
LOCAL_MOCK=true/host/proc/{pid}/root
生产模式/proc/{pid}/root
子进程 rootfs{rootfs}/proc/{subPid}/root

subPid 为空或 0 时表示访问主进程 rootfs。

容器定位接口

GET /panel-api/v1/pid

功能:获取目标容器的文件访问信息。

鉴权:需要用户 token。该接口带 1 分钟响应缓存。

请求参数:

参数位置必填类型说明
namespacequery/formstring原始 Pod 所在命名空间
HostIpquery/formstring目标 Pod 所在节点 IP;注意参数名首字母大写
containerIdquery/formstring容器 ID;有值时可用于定位 PID
podNamequery/formstring原始 Pod 名称
containerNamequery/formstring原始容器名

响应字段均为字符串:

字段类型说明
podNamestringAgent Pod 名称,不一定是原始业务 Pod 名称
pidstring主进程 PID
subPidstring子进程 PID;无子进程时为空字符串
namespacestringAgent Pod namespace
containerNamestringAgent Pod 第一个容器名
podIpstringAgent Pod IP,也用于生产代理地址
webdavUrlstringWebDAV 访问基础路径
webdavBasePathstring编辑器用于截断/展示路径的基础路径,不带开头 /
compressUrlstring压缩/解压 API 基础路径
permissionUrlstring权限修改 API 基础路径
pwdstring初始工作目录
agentUrlstringAgent 代理基础路径
webdavTokenstring文件访问 token,当前等于用户 token

生产模式响应示例:

json
{
  "podName": "w7panel-agent-abcde",
  "pid": "12345",
  "subPid": "",
  "namespace": "default",
  "containerName": "agent",
  "podIp": "10.0.0.10",
  "webdavUrl": "/panel-api/v1/10.0.0.10:8000/proxy/panel-api/v1/files/webdav-agent/12345/agent",
  "webdavBasePath": "panel-api/v1/files/webdav-agent/12345/agent",
  "compressUrl": "/panel-api/v1/10.0.0.10:8000/proxy/panel-api/v1/files/compress-agent/12345",
  "permissionUrl": "/panel-api/v1/10.0.0.10:8000/proxy/panel-api/v1/files/permission-agent/12345",
  "pwd": "/",
  "agentUrl": "/panel-api/v1/10.0.0.10:8000/proxy",
  "webdavToken": "eyJ..."
}

子进程响应中的 URL 会包含 /subagent/{subPid}

json
{
  "pid": "12345",
  "subPid": "67890",
  "webdavUrl": "/panel-api/v1/10.0.0.10:8000/proxy/panel-api/v1/files/webdav-agent/12345/subagent/67890/agent",
  "compressUrl": "/panel-api/v1/10.0.0.10:8000/proxy/panel-api/v1/files/compress-agent/12345/subagent/67890",
  "permissionUrl": "/panel-api/v1/10.0.0.10:8000/proxy/panel-api/v1/files/permission-agent/12345/subagent/67890"
}

WebDAV 接口

路径

方法路径鉴权说明
多方法/panel-api/v1/files/webdav-agent/:pid/agent/*path需要 token访问主进程 rootfs
多方法/panel-api/v1/files/webdav-agent/:pid/subagent/:subpid/agent/*path需要 token访问子进程 rootfs
多方法/panel-api/v1/files/webdav-test/*path无鉴权测试入口,映射宿主 /

注册的多方法包括:PROPFINDPROPPATCHMKCOLCOPYMOVELOCKUNLOCKLINKUNLINKGETPUTDELETEHEADOPTIONSPATCHPOST

请求参数

参数位置必填类型说明
pidpathstring主进程 PID
subpidpath子进程接口必填string子进程 PID
pathpathstring容器内路径;空路径按 / 处理
bodybodyPUT 时必填bytes写入文件内容

常用 Header:

Header必填说明
Authorization: Bearer {webdavToken}文件访问 token
DepthPROPFIND 时常用01
DestinationMOVE/COPY 时必填目标 URL 或目标路径;代理层会改写 WebDAV Destination 路径
OverwriteMOVE/COPY 时可选是否覆盖目标
Content-TypePUT 时建议文件 MIME 或 application/octet-stream

响应

方法成功响应说明
GETbytes文件内容;目录或不可读特殊文件会按 WebDAV 错误处理
PROPFINDXMLWebDAV multistatus
PUTWebDAV 状态码写入成功
DELETEWebDAV 状态码删除成功
MKCOLWebDAV 状态码创建目录成功
MOVE/COPYWebDAV 状态码移动或复制成功

PROPFIND 会额外返回 w7panel 命名空间属性:

属性类型说明
uidstring文件 uid
gidstring文件 gid
modestring八进制权限,例如 644
typestringfiledirectorysymlinkdevicefifosocketunknown
editablebool string是否可读写编辑;特殊文件和越界 symlink 为 false

限制和行为:

说明
目录最大条目单次 Readdir 最多 5000 项
特殊文件device/fifo/socket/unknown 不允许 Read/Seek
symlink指向容器 rootfs 外部的 symlink 会标记为不可编辑
Content-Type普通文件按扩展名推断,未知为 application/octet-stream;非普通文件为 application/linux-file

请求示例:

http
PROPFIND /panel-api/v1/files/webdav-agent/12345/agent/etc
Authorization: Bearer <webdavToken>
Depth: 1
http
PUT /panel-api/v1/files/webdav-agent/12345/agent/tmp/hello.txt
Authorization: Bearer <webdavToken>
Content-Type: text/plain

hello

压缩解压

POST /compress

请求体可用 JSON 或 form:

字段必填类型说明
sourcesarray[string]要压缩的容器内路径列表
outputstring输出压缩包容器内路径

格式由 output 扩展名决定:

扩展名行为
.zip 或未知扩展名ZIP
.tartar
.tar.gz / .tgztar + gzip
.tar.xz / .txztar + xz
.tar.bz2 / .tbz2当前代码会进入 bzip2 压缩分支,但返回 bzip2 compression not supported

请求示例:

http
POST /panel-api/v1/files/compress-agent/12345/compress
Authorization: Bearer <webdavToken>
Content-Type: application/json

{
  "sources": ["/etc/nginx", "/var/log/nginx/access.log"],
  "output": "/tmp/nginx.tar.gz"
}

成功响应:JSON 字符串 "success"

POST /extract

请求体可用 JSON 或 form:

字段必填类型说明
sourcestring压缩包容器内路径
targetstring解压目标目录,目录不存在会自动创建

支持解压格式:

扩展名说明
.zipZIP
.tartar;也会尝试自动识别 gzip/xz/bzip2 tar 流
.tar.gz / .tgztar + gzip
.tar.bz2 / .tbz2tar + bzip2
.tar.xz / .txztar + xz
.7z7z
未知扩展名默认按 zip/自动检测逻辑处理

安全限制:解压 ZIP/TAR/7z 时会检查目标路径,阻止 ../ 这类路径穿越写出目标目录。

请求示例:

http
POST /panel-api/v1/files/compress-agent/12345/extract
Authorization: Bearer <webdavToken>
Content-Type: application/json

{
  "source": "/tmp/site.zip",
  "target": "/var/www/html"
}

成功响应:JSON 字符串 "success"

权限修改

POST /chmod

请求体可用 JSON 或 form:

字段必填类型说明
pathstring容器内文件路径
modestring八进制权限字符串,例如 7550644
recursivebool是否递归;递归时对目录树内每个路径执行 os.Chmod

请求示例:

json
{
  "path": "/var/www/html/index.php",
  "mode": "755",
  "recursive": false
}

成功响应:JSON 字符串 "success"

POST /chown

请求体可用 JSON 或 form:

字段必填类型说明
pathstring容器内文件路径
ownerstringowner 表达式
recursivebool是否递归;递归时对目录树内每个路径执行 os.Chown

owner 解析规则:

写法行为
1000uid 和 gid 都设为 1000
rootuid 设为 0,gid 保持默认 0
root:root / root.rootuid/gid 都设为 0
其它用户名/组名当前仅内置识别 root;无法识别时为 -1,由 os.Chown 按系统语义处理

请求示例:

json
{
  "path": "/var/www/html",
  "owner": "root:root",
  "recursive": true
}

成功响应:JSON 字符串 "success"

下载、复制和移动

GET /panel-api/v1/download/*path

功能:从 s3.base_dir 下载文件。

请求参数:

参数位置必填类型说明
pathpathstring相对 s3.base_dir 的文件路径

成功响应:文件流。

响应 Header:

Header说明
Content-Typeapplication/octet-stream
Content-Dispositionattachment; filename={服务端文件完整路径}

错误:文件不存在返回 404

POST /panel-api/v1/cppid

功能:在 s3.base_dir 与容器 rootfs 路径之间复制文件或目录。

POST /panel-api/v1/mvpid 当前绑定到同一个 CpPidFile 方法,行为与 /cppid 相同,并不是 rename/move。

请求参数:

参数位置必填类型说明
fromquery/form/bodystring源路径
toquery/form/bodystring目标路径
uploadquery/form/bodystring1 表示从 s3.base_dir/from 复制到容器路径 to;其它值表示从容器路径 from 复制到 s3.base_dir/to
pidquery/form/bodystring目标 PID;当前实现只校验必填,路径转换由 procpath.ConvertToLocalPath 处理

成功响应:JSON 字符串 "success"

POST /panel-api/v1/cp

功能:使用 kubectl cp 在 s3.base_dir 与 Pod 之间复制文件。

请求参数:

参数位置必填类型说明
fromquery/form/bodystring源路径
toquery/form/bodystring目标路径
namespacequery/form/bodystringPod namespace
uploadquery/form/bodystring1 表示从 s3.base_dir/from 上传到 podName:to;其它值表示从 podName:from 下载到 s3.base_dir/to
podNamequery/form/bodystringPod 名称

成功响应:JSON 字符串 "success"

POST /panel-api/v1/files/mvtopod

功能:将系统临时目录中的文件移动到目标容器 rootfs。

请求参数:

参数位置必填类型说明
pidquery/form/bodystring主进程 PID
subpidquery/form/bodystring子进程 PID;0 会被当作空值
fromPathquery/form/bodystring相对 os.TempDir() 的源路径
toPathquery/form/bodystring容器内目标路径

成功响应:JSON 字符串 "success"

分片上传

分片上传先写入 s3.base_dir/.chunks/{identifier}。合并时:

场景合并目标
未传 pidpid=0s3.base_dir/{fileName}
传入 pid{rootfs}/{fileName}subPid 非空时使用子进程 rootfs

POST /panel-api/v1/files/upload-chunk

请求类型:multipart/form-data

请求参数:

参数位置必填类型说明
fileform filefile当前分片文件
chunkIndexformstring/int分片序号,从 0 开始
chunkTotalformstring/int总分片数
identifierformstring文件唯一标识,通常为文件 hash
fileNameformstring原始文件名,仅用于日志
relativePathformstring预留字段,当前未使用
fileSizeformstring/int64文件总大小,当前仅解析预留

响应字段:

字段类型说明
chunkExistsbool分片是否已存在
chunkIndexint分片序号
chunkTotalint总分片数;分片已存在时不返回
writtenint64本次写入字节数;分片已存在时不返回

上传成功示例:

json
{
  "chunkExists": false,
  "chunkIndex": 0,
  "chunkTotal": 3,
  "written": 1048576
}

分片已存在示例:

json
{
  "chunkExists": true,
  "chunkIndex": 0
}

GET /panel-api/v1/files/check-chunk

请求参数:

参数位置必填类型说明
identifierquerystring文件唯一标识
chunkIndexquerystring/int分片序号
chunkTotalquerystring/int总分片数
fileNamequerystring文件名
relativePathquerystring相对路径

响应字段:

字段类型说明
chunkExistsbool分片是否存在

POST /panel-api/v1/files/merge-chunks

请求类型:application/json

请求参数:

字段必填类型说明
identifierstring文件唯一标识
fileNamestring合并后的文件名或相对路径
totalChunksint总分片数
fileSizeint64文件总大小,当前预留
pidstring目标容器 PID
subPidstring子进程 PID

响应字段:

字段类型说明
fileUrlstring下载 URL;直接合并到容器 rootfs 时该 URL 可能不适合下载
fileNamestring文件名
fileSizeint64合并后写入字节数

响应示例:

json
{
  "fileUrl": "/panel-api/v1/download/upload/demo.zip",
  "fileName": "upload/demo.zip",
  "fileSize": 3145728
}

错误:

场景状态码说明
分片目录不存在400chunk directory not found
缺少指定分片400missing chunk {index}
创建目录/文件失败500返回底层错误

挂载文件接口

挂载文件接口用于读取和修改工作负载 PodSpec 中通过 ConfigMap、Secret、Projected 挂载出来的文件。支持的工作负载必须能从对象中解析 spec.template.spec

GET /panel-api/v1/mountfiles

功能:获取工作负载中的挂载文件列表。

请求参数:

参数位置必填类型说明
namespacequery/formstring命名空间,空时使用当前 SDK 默认 namespace
apiVersionquery/formstring工作负载 apiVersion,例如 apps/v1
kindquery/formstring工作负载 kind,例如 Deployment
namequery/formstring工作负载名称
includeContentquery/formbool是否读取 ConfigMap/Secret 内容

响应字段:

字段类型说明
namespacestring命名空间
apiVersionstring工作负载 apiVersion
kindstring工作负载 kind
namestring工作负载名称
mountsarray[object]挂载说明列表

mounts[] 字段:

字段类型说明
containerNamestring容器名
containerTypestringcontainerinitContainer
volumeNamestringVolume 名称
mountPathstring容器挂载路径
subPathstringvolumeMount subPath,可能为空
readOnlybool是否只读
sourceTypestring来源类型:configMapsecretserviceAccountToken
sourceNamestringConfigMap/Secret 名称
filesarray[object]文件列表

mounts[].files[] 字段:

字段类型说明
pathstring容器内绝对路径
relativePathstring相对挂载路径
sourceTypestring来源类型
sourceNamestringConfigMap/Secret 名称
keystringConfigMap/Secret key
optionalbool是否 optional
modeint32文件 mode 数值
modeOctalstring八进制 mode,例如 0644
contentstring文本内容,仅 includeContent=true 且内容为文本时返回
contentBase64string二进制内容 base64,仅 includeContent=true 且内容为二进制时返回
binarybool是否二进制

响应示例:

json
{
  "namespace": "default",
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "name": "demo",
  "mounts": [
    {
      "containerName": "web",
      "containerType": "container",
      "volumeName": "config",
      "mountPath": "/etc/nginx/conf.d",
      "readOnly": true,
      "sourceType": "configMap",
      "sourceName": "demo-config",
      "files": [
        {
          "path": "/etc/nginx/conf.d/default.conf",
          "relativePath": "default.conf",
          "sourceType": "configMap",
          "sourceName": "demo-config",
          "key": "default.conf",
          "modeOctal": "0644",
          "content": "server { listen 80; }"
        }
      ]
    }
  ]
}

POST /panel-api/v1/mountfiles

功能:创建挂载文件。当前实现会新建 ConfigMap,并把文件挂载到匹配容器的 PodSpec。

请求参数:

参数位置必填类型说明
namespacequery/form/bodystring命名空间
apiVersionquery/form/bodystring工作负载 apiVersion
kindquery/form/bodystring工作负载 kind
namequery/form/bodystring工作负载名称
pathquery/form/bodystring要创建的容器内绝对路径
containerNamequery/form/bodystring容器名;用于选择挂载目标
contentquery/form/bodystring文件内容
modequery/form/bodystring文件权限,例如 0644

行为:

说明
ConfigMap 名称w7-mf-{workloadName}-{fileName} 形式,具体以 buildMountFileConfigMapName 为准
Volume 名称基于文件名生成,具体以 buildMountFileVolumeName 为准
文件 keypath.Base(path)
默认 modeKubernetes ConfigMap volume 默认 mode

成功响应:JSON 字符串 "success"

PUT /panel-api/v1/mountfiles

功能:更新已有挂载文件内容。

请求参数:

参数位置必填类型说明
namespacequery/form/bodystring命名空间
apiVersionquery/form/bodystring工作负载 apiVersion
kindquery/form/bodystring工作负载 kind
namequery/form/bodystring工作负载名称
pathquery/form/bodystring已挂载文件的容器内绝对路径
contentquery/form/bodystring新内容

行为:

来源更新方式
configMap更新 ConfigMap.data[key];若原 key 在 binaryData 中,则写入 binaryData[key]
secret更新 Secret.data[key],内容按字节写入
其它来源返回不支持错误

成功响应:JSON 字符串 "success"

DELETE /panel-api/v1/mountfiles

功能:删除已有挂载文件。

请求参数:

参数位置必填类型说明
namespacequery/form/bodystring命名空间
apiVersionquery/form/bodystring工作负载 apiVersion
kindquery/form/bodystring工作负载 kind
namequery/form/bodystring工作负载名称
pathquery/form/bodystring已挂载文件的容器内绝对路径

行为:

来源删除方式
configMap删除对应 key;若 ConfigMap 只有一个条目,会移除 PodSpec 中相关 volume 并删除 ConfigMap
secret删除对应 key,并移除 PodSpec 中该文件引用

成功响应:JSON 字符串 "success"

PUT /panel-api/v1/mountfiles/chmod

功能:修改挂载文件在 PodSpec 中的 mode。

请求参数:

参数位置必填类型说明
namespacequery/form/bodystring命名空间
apiVersionquery/form/bodystring工作负载 apiVersion
kindquery/form/bodystring工作负载 kind
namequery/form/bodystring工作负载名称
pathquery/form/bodystring已挂载文件的容器内绝对路径
modequery/form/bodystring文件权限,例如 0644

成功响应:JSON 字符串 "success"。若路径没有挂载,返回错误:path {path} 没有挂载

开发检查

  • WebDAV 必须保持标准协议响应,尤其 PROPFIND 必须返回 XML。
  • 后端修改 webdavUrlcompressUrlpermissionUrlwebdavBasePath 时,必须同步检查前端和 Codeblitz。
  • LOCAL_MOCK=true 只影响 /host/proc 路径选择,不跳过 Auth。
  • 文件路径要避免让用户自行拼接生产 Agent 代理路径,优先使用 /pid 返回值。
  • 新增压缩格式、WebDAV 属性、分片字段或挂载文件字段时,需要同步本文档、前端类型和相关测试。