init error: AppInfoNotExists won't start session
GET https://o.wpsgo.com/api/v3/office/file/28/multiwatermark 403 (Forbidden)
WPS SDK 在初始化时会:
结论:必须实现后端回调接口,WPS SDK 才能正常工作。
接口地址:
GET /v1/3rd/file/info
请求参数(Query):
_w_appid: WPS 应用ID(SX20251229FLIAPDAPP)_w_fileid: 文件ID(前端传递的 fileId)请求头:
X-WebOffice-Token: {前端传递的 token}
X-User-Query: {前端传递的 customArgs,JSON 格式}
响应格式:
{
"code": 0,
"msg": "success",
"data": {
"file": {
"id": "28",
"name": "万颗星临床营养系统接口文档.pdf",
"version": 1,
"size": 1234567,
"download_url": "http://img.tpidea.cn/2025/12/29/d94280895eac4a499da425a3564c69b7.pdf",
"creator": {
"id": "user_1",
"name": "张三"
},
"create_time": 1735459200,
"modify_time": 1735459200,
"user_acl": {
"rename": 1,
"history": 1,
"copy": 1,
"export": 1,
"print": 1,
"read": 1,
"update": 1,
"comment": 1
}
}
}
}
字段说明:
id: 文件ID,必须与请求的 _w_fileid 一致name: 文件名version: 文件版本号,从 1 开始size: 文件大小(字节)download_url: 文件下载地址,必须是可访问的 HTTP/HTTPS URLcreator: 创建者信息create_time: 创建时间(Unix 时间戳,秒)modify_time: 修改时间(Unix 时间戳,秒)user_acl: 用户权限配置
rename: 是否允许重命名(1=允许,0=不允许)history: 是否允许查看历史版本copy: 是否允许复制export: 是否允许导出print: 是否允许打印read: 是否允许查看(必须为 1)update: 是否允许编辑(1=允许,0=只读)comment: 是否允许批注在 WPS 开放平台控制台配置:
https://你的域名/v1/3rd/file/infohttps://你的域名/v3/3rd/filesGET /v3/3rd/files/:file_id/upload/prepare
响应:
{
"code": 0,
"data": {
"digest_types": ["sha1", "md5"]
}
}
POST /v3/3rd/files/:file_id/upload/address
请求体:
{
"name": "文档.pdf",
"size": 1234567,
"digest": {
"sha1": "abc123..."
},
"is_manual": true
}
响应:
{
"code": 0,
"data": {
"method": "PUT",
"url": "https://your-oss.com/upload/file123",
"headers": {},
"send_back_params": {}
}
}
POST /v3/3rd/files/:file_id/upload/complete
请求体:
{
"request": {
"name": "文档.pdf",
"size": 1234567,
"digest": { "sha1": "abc123..." },
"is_manual": true
},
"response": {
"status_code": 200,
"headers": {}
}
}
响应:
{
"code": 0,
"data": {
"id": "28",
"name": "文档.pdf",
"version": 2,
"size": 1234567,
"create_time": 1735459200,
"modify_time": 1735459300,
"creator_id": "user_1",
"modifier_id": "user_1"
}
}
GET /v1/3rd/file/info// 文件信息接口
app.get('/v1/3rd/file/info', async (req, res) => {
const { _w_appid, _w_fileid } = req.query;
// 验证 appId
if (_w_appid !== 'SX20251229FLIAPDAPP') {
return res.status(403).json({ code: 403, msg: 'Invalid appId' });
}
// 从数据库获取文件信息
const document = await getDocumentById(_w_fileid);
if (!document) {
return res.status(404).json({ code: 404, msg: 'File not found' });
}
// 返回文件信息
res.json({
code: 0,
msg: 'success',
data: {
file: {
id: document.id.toString(),
name: document.fileName,
version: document.version || 1,
size: document.fileSize || 0,
download_url: document.url,
creator: {
id: document.creatorId?.toString() || 'user_1',
name: document.creatorName || '未知用户'
},
create_time: Math.floor(new Date(document.createTime).getTime() / 1000),
modify_time: Math.floor(new Date(document.updateTime).getTime() / 1000),
user_acl: {
rename: 1,
history: 1,
copy: 1,
export: 1,
print: 1,
read: 1,
update: 1, // 1=可编辑,0=只读
comment: 1
}
}
}
});
});
@RestController
@RequestMapping("/v1/3rd/file")
public class WpsFileController {
@Autowired
private DocumentService documentService;
@GetMapping("/info")
public ResponseEntity<?> getFileInfo(
@RequestParam("_w_appid") String appId,
@RequestParam("_w_fileid") String fileId
) {
// 验证 appId
if (!"SX20251229FLIAPDAPP".equals(appId)) {
return ResponseEntity.status(403)
.body(Map.of("code", 403, "msg", "Invalid appId"));
}
// 获取文件信息
Document document = documentService.getById(Long.parseLong(fileId));
if (document == null) {
return ResponseEntity.status(404)
.body(Map.of("code", 404, "msg", "File not found"));
}
// 构建响应
Map<String, Object> response = new HashMap<>();
response.put("code", 0);
response.put("msg", "success");
Map<String, Object> fileInfo = new HashMap<>();
fileInfo.put("id", document.getId().toString());
fileInfo.put("name", document.getFileName());
fileInfo.put("version", document.getVersion() != null ? document.getVersion() : 1);
fileInfo.put("size", document.getFileSize() != null ? document.getFileSize() : 0);
fileInfo.put("download_url", document.getUrl());
Map<String, Object> creator = new HashMap<>();
creator.put("id", document.getCreatorId() != null ? document.getCreatorId().toString() : "user_1");
creator.put("name", document.getCreatorName() != null ? document.getCreatorName() : "未知用户");
fileInfo.put("creator", creator);
fileInfo.put("create_time", document.getCreateTime().getTime() / 1000);
fileInfo.put("modify_time", document.getUpdateTime().getTime() / 1000);
Map<String, Integer> userAcl = new HashMap<>();
userAcl.put("rename", 1);
userAcl.put("history", 1);
userAcl.put("copy", 1);
userAcl.put("export", 1);
userAcl.put("print", 1);
userAcl.put("read", 1);
userAcl.put("update", 1); // 1=可编辑,0=只读
userAcl.put("comment", 1);
fileInfo.put("user_acl", userAcl);
response.put("data", Map.of("file", fileInfo));
return ResponseEntity.ok(response);
}
}
GET http://localhost:8080/v1/3rd/file/info?_w_appid=SX20251229FLIAPDAPP&_w_fileid=28
curl "http://localhost:8080/v1/3rd/file/info?_w_appid=SX20251229FLIAPDAPP&_w_fileid=28"
确保响应格式完全符合上面的 JSON 格式。
原因:
解决:
原因:
解决:
原因:
解决:
GET /v1/3rd/file/info 接口