本文详解如何在 autodesk platform services(aps,原 forge)中正确创建存储桶(bucket),涵盖身份认证、请求参数规范、常见 400 错误排查及前后端协同要点,助你稳定完成模型上传前的基础设施配置。
本文详解如何在 autodesk platform services(aps,原 forge)中正确创建存储桶(bucket),涵盖身份认证、请求参数规范、常见 400 错误排查及前后端协同要点,助你稳定完成模型上传前的基础设施配置。
在 Autodesk Platform Services(APS)生态中,Bucket 是存放设计模型、纹理、SVF 资源等对象的核心存储单元。它并非 Forge Viewer 的内置功能,而是由 OSS(Object Storage Service)API 提供的底层服务——Viewer 仅负责加载已成功上传并翻译(translate)后的模型资源。因此,“在 Forge Viewer 中创建 Bucket”这一说法存在概念偏差;实际流程应为:通过 OSS API 创建 Bucket → 上传文件 → 调用 Model Derivative API 进行格式转换 → 最终由 Forge Viewer 加载 SVF/SVF2 衍生文件。
以下为你梳理关键实现步骤与排错要点:
✅ 1. 前提条件:确保 OAuth 2.0 凭据与权限完备
- 使用 client_id 和 client_secret 获取 2-legged token(适用于服务端操作,如创建 Bucket、上传、翻译);
- Token 必须包含 data:write 和 bucket:create 权限(推荐 scope:["data:write", "bucket:create"]);
- ⚠️ 关键检查项:APS 开发者门户中应用的 Callback URL 必须与代码中发起 OAuth 流程的实际回调地址完全一致(含协议、域名、端口、路径)。即使仅使用 2-legged 认证,部分 SDK 或中间件仍会校验该配置,不匹配将导致签名失败,最终返回 400 Bad Request。
✅ 2. Bucket Key 命名规范(高频错误根源)
Bucket Key 必须满足严格格式要求:
- 全小写(a–z)、数字(0–9)、连字符(-)和下划线(_);
- 长度 3–128 字符;
- 必须全局唯一(APS 平台级唯一,非用户级);
- ❌ 禁止使用大写字母、点号(.)、斜杠(/)、空格等特殊字符。
你当前代码中 config.credentials.client_id.toLowerCase() + '-' + req.body.bucketKey 是良好实践,但需确保 req.body.bucketKey 自身已清洗(如前端 $('#newBucketKey').val().trim().replace(/[^a-z0-9_-]/g, ''))。
✅ 3. 正确调用 createBucket API(Node.js + APS SDK 示例)
const { BucketsApi, PostBucketsPayload } = require('forge-apis');
// ✅ 推荐:显式构造 payload 并校验
router.post('/buckets', async (req, res, next) => {
const bucketKey = (req.body.bucketKey || '').trim();
if (!bucketKey) {
return res.status(400).json({ error: 'bucketKey is required and cannot be empty' });
}
const payload = new PostBucketsPayload();
payload.bucketKey = `${config.credentials.client_id.toLowerCase()}-${bucketKey}`; // 如 'myapp-prod-models'
payload.policyKey = 'persistent'; // 注意:值为 'persistent'(小写),非 'Persistent'
try {
const bucketsApi = new BucketsApi();
const result = await bucketsApi.createBucket(
payload,
{}, // opts(可选)
req.oauth_client, // 2-legged client instance
req.oauth_token // valid 2-legged token with bucket:create scope
);
res.status(201).json(result); // ✅ 返回 201 Created 及 bucket 信息
} catch (err) {
console.error('Failed to create bucket:', err.response?.body || err.message);
next(err);
}
});? 注意事项:
- policyKey 只接受 'transient' 或 'persistent'(全小写),文档中常误写为 'Transient'/'Persistent',这是导致 400 的典型原因;
- 使用 res.status(201) 更符合 REST 规范(资源创建成功);
- 建议捕获 err.response?.body 输出详细错误(如 { "reason": "Invalid bucket key format" }),便于精准定位。
✅ 4. 前端调用建议(增强健壮性)
function createNewBucket() {
const bucketKey = $('#newBucketKey').val().trim().replace(/[^a-z0-9_-]/g, '');
if (!bucketKey) {
alert('请输入有效的 bucketKey(仅含小写字母、数字、-、_)');
return;
}
$.ajax({
url: '/api/forge/oss/buckets',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ bucketKey }), // ✅ 直接传字符串,无需额外包装
headers: {
'Authorization': 'Bearer ' + getAccessToken() // 确保 token 已刷新且有效
},
success: function (res) {
$('#userHubs').jstree(true).refresh();
$('#createBucketModal').modal('hide');
alert('Bucket 创建成功:' + res.bucketKey);
},
error: function (xhr) {
const msg = xhr.responseJSON?.reason || xhr.statusText;
alert(`创建失败:${xhr.status} ${msg}`);
console.error('Bucket creation error:', xhr);
}
});
}? 总结:400 Bad Request 的五大自查清单
| 检查项 | 是否合规 | 说明 |
|---|---|---|
| ✅ Callback URL 一致性 | □ | APS 应用设置页 vs 代码中 OAuth redirect_uri 必须一字不差 |
| ✅ Token scope | □ | 必含 bucket:create,推荐 data:write bucket:create |
| ✅ bucketKey 格式 | □ | 全小写、3–128 字符、仅含 [a-z0-9_-] |
| ✅ policyKey 值 | □ | 仅支持 'transient' 或 'persistent'(全小写) |
| ✅ 请求头与 body | □ | Content-Type: application/json,body 为 {"bucketKey":"xxx"} |
完成上述配置后,Bucket 创建即可稳定运行。后续可无缝衔接文件上传(BucketsApi.uploadObject)与模型翻译(ModelDerivativeApi.translate),最终交由 Forge Viewer 渲染——这才是 APS 全链路的标准工作流。

















