资源直传 API
本站负责鉴权、调度、容量和上传确认。文件分片由浏览器或其他客户端直接 PUT 到存储服务,文件内容不经过本站。
当前模式:客户端直传。图片最大 50 MiB,视频最大 200 MiB;同时受账户和套餐限制。
鉴权与跨域
在用户中心创建个人 API 密钥,调用控制接口时传入 Authorization: Bearer sk-...。支持任意 Origin 的 CORS 预检,无需跨域 Cookie。浏览器使用调用者自己的用户密钥,勿在公开前端硬编码管理员或项目共用密钥。
本站前台使用登录会话或访客会话及 X-CSRF-Token。存储桶必须配置 PUT / GET / HEAD 的跨域规则,管理员可在统一存储账户编辑页配置。
1. 申请直传
POST /api/direct_upload.php,Content-Type: application/json,仅传递元数据:
{"action":"prepare","filename":"example.mp4","size":142534300,"mime":"video/mp4"}
文件格式按扩展名白名单处理:JPG / JPEG / PNG / GIF / WEBP / BMP / MP4 / WebM / MOV。直传不读取文件内容,无法提供服务端解码或内容真实性检测。
{
"code": 200,
"data": {
"upload_id": "上传任务编号",
"upload_token": "该任务的操作凭证",
"expires_at": 1793510000,
"part_size": 8388608,
"parts": [
{"part_number":1,"offset":0,"size":8388608,"method":"PUT",
"url":"https://存储服务/...?短期签名","headers":{}}
],
"transfer": "direct"
}
}
2. 直接上传分片
依次把每个分片对应的原始字节直接 PUT 到它的 url,不使用 multipart/form-data。精确遵守 offset / size,不修改签名 URL。浏览器 Blob 会自动提供已签名的 Content-Length。不要向存储服务发送本站 Cookie、API 密钥或 Authorization 头。单个分片失败可以重复 PUT;任务完成后旧分片 URL 不能覆写成品。
3. 确认完成
{"action":"complete","upload_id":"任务编号","upload_token":"任务操作凭证"}
使用相同控制接口和鉴权。本站读取存储分片清单,核对数量及每片大小,通知存储合并,再 HEAD 核对总大小和对象标识;不下载文件。确认可重试,容量只记一次。
{
"code": 200,
"path": "http://tc.yjsir.com/image.php?id=永久编号",
"data": {
"url": "http://tc.yjsir.com/image.php?id=永久编号",
"permanent_url": "http://tc.yjsir.com/image.php?id=永久编号",
"download_url": "https://当前存储池的资源地址或签名地址",
"download_url_expires_in": 3600,
"filename": "example.mp4", "size": 142534300,
"mime": "video/mp4", "media_type": "video", "transfer": "direct"
}
}
长期保存 permanent_url / url。本站仅用 302 跳转到文件对应存储池;下载和视频分段请求由存储服务承接。私有桶 download_url 有效期 1 小时,不能作为永久链接。账户绑定公共资源域名后返回该域名,过期字段为 null。不同账户可使用不同资源域名。
取消与中断
{"action":"abort","upload_id":"任务编号","upload_token":"任务操作凭证"}取消成功后释放未完成任务的预占容量;重复取消安全。已经完成的任务返回资源结果。凭证有效 1 小时,中断任务由后台定时核对、取消;网络异常时保守保留容量。上传或读取最终目标会显示存储域名。
浏览器接入示例
<script src="http://tc.yjsir.com/assets/direct-upload.js"></script>
<input type="file" id="file">
<script>
document.querySelector('#file').onchange = async (event) => {
const file = event.target.files[0];
const result = await storageDirectUpload(file, {
endpoint: 'http://tc.yjsir.com/api/direct_upload.php',
apiKey: '调用者自己的用户 API 密钥',
onProgress: fraction => console.log(Math.round(fraction * 100) + '%')
});
console.log('永久链接', result.data.permanent_url);
console.log('立即直连', result.data.download_url);
};
</script>
旧接口与错误
直传模式下旧 multipart 上传接口返回 409 并提示迁移,不能自动把旧式上传变成客户端直传。原有 S3 链接继续有效,通过跳转直连存储;历史本地资源需先迁移到对象存储。401:密钥无效;403:无权限或 CSRF 失败;409:模式、任务或元数据冲突;413:超过限制;415:内容类型错误;503:存储控制服务暂时不可用。不要将短期上传 URL 和任务凭证发给其他用户。