# 入职资料 Base64 上传接口 `POST http://服务器:8104/api/tianpai/dingtalk/drive/onboarding/upload` 请求头:`Content-Type: application/json`。 ```json { "fileName": "张三-入职资料.pdf", "base64": "文件内容的Base64字符串" } ``` `fileName` 和 `base64` 必填。`base64` 也可写成 `fileBase64`,支持纯 Base64、包含换行的 Base64,以及 `data:application/pdf;base64,...`。默认解码后最多 20 MiB;不接收空文件。 调用方只需传文件名和 Base64,不需要传 `userId`、`unionId`、空间ID或文件夹ID。后台默认使用钉钉员工 UserID **32600011**,先查询用户详情取得 unionId,再以该用户身份操作钉盘。请求中额外传入身份字段也不会覆盖后台用户。 不再查询主管理员列表。后台分页查询该用户可见的团队空间(`spaceType=org`),再分页检查各空间根目录下名称完全等于“入职资料”的文件夹。找到唯一目录后,使用实际返回的空间和文件夹ID上传。未找到、多空间重名、权限不足或分页未完成时返回失败,不会任意选择第一项,也不会把个人文件空间当成团队文件。 ## 首次部署配置 复用项目现有 `AccessTokenService.getAccessToken()` 的应用凭据,无需再添加 AppKey/AppSecret。 默认无需新增配置。以下配置只用于服务端指定上传用户、消除重名目录歧义或调整文件大小: | 环境变量 | 说明 | | --- | --- | | `DINGTALK_DRIVE_SPACE_ID` | 可选,指定团队空间;留空时自动查找所有可见团队空间 | | `DINGTALK_DRIVE_ONBOARDING_FOLDER_ID` | 可选,已有“入职资料”文件夹的 storage API dentry.id;指定时必须同时指定空间ID | | `DINGTALK_DRIVE_OPERATOR_USER_ID` | 默认32600011;配置为空时也回退为32600011 | | `DINGTALK_DRIVE_MAX_FILE_BYTES` | 可选,默认20971520,最大104857600 | 也可设置同名含义的 Spring 配置 `dingtalk.drive.space-id`、`onboarding-folder-id`、`operator-user-id`、`max-file-bytes`。环境变量修改后需重启服务。指定目录时不能使用知识库 workspaceId,也不要将整个团队空间根目录误填为入职资料。 AppKey/AppSecret 用于获取应用凭据,后台通过用户详情接口解析32600011的 unionId。空间及文件夹ID来自真实查询结果,不把“团队文件”“入职资料”两个名称直接当成ID。 应用需要开通团队空间查询、文件查询、目录创建、获取上传信息、提交文件及用户详情查询(`/topapi/v2/user/get`)权限。用户32600011需要在通讯录授权范围内,并对目标目录有读写权限。 2026-10-19只读联调已确认:32600011可解析为钉钉用户,团队空间列表查询成功;查询空间根目录时被钉钉拒绝,错误码为 `Forbidden.AccessDenied.AccessTokenPermissionDenied`,明确缺少 **`Drive.File.Read`**。请在开放平台[开通该应用的文件读取权限](https://open-dev.dingtalk.com/appscope/apply?content=ding4fn4g3vzglff2bxy%23Drive.File.Read)。该权限未开通前无法确认真实“入职资料”文件夹ID,也无法完成上传联调。 ## 行为及响应 北京时间 2026-10-19 的文件保存至 `团队文件/入职资料/2026/10/19/张三-入职资料.pdf`。年、月、日三层目录逐层查询,不存在就创建。已有入职资料目录默认自动查找,本接口不会新建团队空间或入职资料根目录。 成功响应示意(ID均以真实返回为准): ```json { "success": true, "code": 200, "message": "上传成功", "data": { "spaceId": "实际空间ID", "fileId": "实际文件ID", "fileName": "张三-入职资料.pdf", "size": 12345, "parentId": "当天目录ID", "path": "团队文件/入职资料/2026/10/19/张三-入职资料.pdf" } } ``` 成功前会回读文件,验证ID、名称、空间、父目录及大小。当前日期目录已有同名文件时返回失败,请更换文件名;不同日期可使用相同文件名。不设置 overwriteDentryId,不主动覆盖已有文件。 接口沿用项目 `R` 响应,业务失败通过 `success:false` 及 `message` 表达。提交超时或提交后核验失败会返回 `data.outcome:"unknown"` 以及可获得的空间/父目录/文件ID;此时可能已经写入,先检查目录,不能盲目重试。 团队空间最多查询100个,每个目录分页有100页、5000项上限,未读完整或出现同名歧义时停止写入。本服务实例内目录创建串行化;多实例同时首次创建时会重新查询,但不保证分布式互斥。调用方需避免并发上传同日同名文件。本接口不提供幂等请求键;客户端/网关超时后也应先检查文件再决定重试。 大文件采用 JSON Base64,网关请求体限制建议至少为原文件大小的4/3再留余量。接口继承项目现有访问控制;部署时应让网关只向授权调用方开放。 ## PowerShell 调用 ```powershell $uploadBody = @{ fileName = '张三-入职资料.pdf' base64 = [Convert]::ToBase64String([IO.File]::ReadAllBytes('D:\资料\张三-入职资料.pdf')) } | ConvertTo-Json Invoke-RestMethod -Method Post ` -Uri 'http://localhost:8104/api/tianpai/dingtalk/drive/onboarding/upload' ` -ContentType 'application/json; charset=utf-8' ` -Body ([Text.Encoding]::UTF8.GetBytes($uploadBody)) ``` 上传逻辑使用隔离单元测试;只读联调仅查询了用户及空间信息。未启动带真实同步任务的 Spring 应用,未向真实钉盘上传测试文件,未创建真实目录。真实上传验证仍需先开通钉钉返回的缺失权限。