# storage.create_upload_session

获取大文件上传用的 presigned URL。这是三步上传流程的第一步：

1. **调用本方法**获取 `upload_url`
2. 通过 **HTTP PUT** 将文件上传到 `upload_url`
3. 调用 **storage.complete_upload** 确认上传完成

> `object_key` 当前仅支持 ASCII 安全字符集合 `[A-Za-z0-9._/-]`，且不允许空路径段、`..` 等非法段。

## 调用示例

```python
result = await client.call("storage.create_upload_session", {
    "object_key": "attachments/report.pdf",
    "size_bytes": 5242880,
    "content_type": "application/pdf"
})
upload_url = result["upload_url"]
# 接下来通过 HTTP PUT 上传文件到 upload_url
```

## 参数

| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `object_key` | string | 是 | — | 对象路径标识 |
| `size_bytes` | integer | 否 | — | 声明的文件大小（字节）。当前实现允许省略，但建议传入用于客户端追踪与最终校验 |
| `content_type` | string | 否 | `"application/octet-stream"` | MIME 类型 |
| `bucket` | string | 否 | `"default"` | 存储桶名称 |
| `owner_aid` | string | 否 | 当前用户 | 所有者 AID |
| `expected_version` | integer | 否 | — | CAS 版本校验（0=必须不存在，>0=必须匹配） |
| `expire_in_seconds` | integer | 否 | `3600` | URL 有效期（秒） |

## 返回值

```json
{
    "upload_url": "https://storage.example.com/upload?key=...&expire=...&sig=...",
    "expire_at": 1711238167,
    "blob_key": "owner_aid_com/default/attachments/report.pdf",
    "owner_aid": "my-agent.agentid.pub",
    "bucket": "default",
    "object_key": "attachments/report.pdf",
    "content_type": "application/pdf",
    "size_bytes": 5242880
}
```

| 字段 | 类型 | 说明 |
|------|------|------|
| `upload_url` | string | 上传 URL，通过 HTTP PUT 上传。签名/鉴权形式由底层 BlobStore 后端决定 |
| `expire_at` | integer | URL 过期时间戳（Unix 秒） |
| `blob_key` | string | 存储后端的对象键 |
| `owner_aid` | string | 对象所有者 AID |
| `bucket` | string | 存储桶名称 |
| `object_key` | string | 对象路径标识 |
| `content_type` | string | MIME 类型 |
| `size_bytes` | integer | 文件大小（字节） |

## 当前实现说明

- 如果底层 BlobStore 返回 `127.0.0.1`、`localhost` 或其他 loopback 地址，storage 服务会把 URL 规范化为对外地址
- 规范化优先使用 `KITE_STORAGE_EXTERNAL_URL`，否则按 `storage.{issuer}` 形式改写
- `create_upload_session` 阶段不会强校验配额或最终文件大小；配额、`max_file_size_bytes`、SHA-256/size 校验会在 `storage.complete_upload` 阶段执行

## 相关方法

- [storage.complete_upload](storage.complete_upload.md) — 确认上传完成（第三步）
- [storage.put_object](storage.put_object.md) — 小文件直接上传（≤64KB）
