返回首页

资源直传 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 和任务凭证发给其他用户。