> This page is for Camera to Cloud.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://next.developer.frame.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://next.developer.frame.io/_mcp/server.

# 操作指南：上传（基础）

## 前言





现在，我们的集成之旅到达了一处激动人心的里程碑：将资产上传到 Frame.io。本指南将带您了解基本上传流程。





## 前提条件

如果您还没有阅读，请在继续之前先查阅[实施 C2C：设置](./implementing-c2c-setting-up)指南。您需要用到在[身份验证和授权流程](./implementing-c2c-authentication-and-authorization)中获取的 `access_token`。在本指南中，我们将使用[此 Frame.io 链接](https://f.io/Rq1q5CzB)中提供的示例测试资产。下载此文件，跟随我们的示例进行操作，这样您就可以匹配示例命令中的值。

## 步骤 1：创建资产

我们来上传一下[示例文件](https://f.io/Rq1q5CzB)，假设它是在 10 秒前创建的。首先，我们需要在 Frame.io 中创建资产引用：

```shell
{
curl -X POST https://api.frame.io/v2/devices/assets \
    --header 'Authorization: Bearer [access_token]' \
    --header 'Content-Type: application/json' \
    --header 'x-client-version: 2.0.0' \
    --data-binary @- <<'__JSON__' 
        {
            "name": "C2C_TEST_CLIP.mp4", 
            "filetype": "video/mp4", 
            "filesize": 21136250,
            "offset": 10
        }
__JSON__
} | python -m json.tool
```




<Info title="API 端点规范">
  `/v2/devices/assets` 的文档可以在[此处找到](/camera-to-cloud/api-reference/device-asset-create)。虽然旧版端点 `/v2/assets` 仍然有效，但我们建议新的集成使用 `/v2/devices/assets`。
</Info>

<Info title="JSON 编码">
  此端点与我们之前使用的身份验证端点不同，它接受 `application/json` 编码而不是 `form/multipart`。它还接受 `application/x-www-form-urlencoded`。
</Info>

<Info title="命令语法">
  此示例使用 [heredoc](https://linuxize.com/post/bash-heredoc/) 向 `curl` 提供多行格式的可读 JSON 负载。`--data-binary @-` 参数指示 `curl` 从 stdin 读取原始数据。[在此](https://unix.stackexchange.com/questions/88490/how-do-you-use-output-redirection-in-combination-with-here-documents-and-cat)了解有关此方法的更多信息。
</Info>


让我们来检查一下 JSON 负载参数：

`name`：Frame.io 中显示的资产名称。该名称不需要与磁盘上的文件名一致。`filetype`：文件的 [MIME 类型](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types)。大多数编程语言都提供进行 MIME 类型检测的实用程序（示例：[Go](https://golangcode.com/get-the-content-type-of-file/)、[Python](https://docs.python.org/3/library/mimetypes.html)）。`filesize`：文件大小（以字节为单位）。我们的示例文件大小约为 21.1 MB。`offset`：文件创建到现在的秒数。如果省略，则默认为 0。必须提供此参数，因为它有助于确定是否应因设备暂停而拒绝文件。我们将在[高级上传指南](./how-to-advanced-uploads)中详细介绍这部分内容。

响应将类似于以下内容（省略了某些字段）：





```json
{
    "_type": "file",
    ...
    "id": "9a280f99-8f4f-46b0-a4b4-ec4c2f95138e",
    ...
    "upload_urls": [
        "https://frameio-uploads-production.s3-accelerate.amazonaws.com/parts/[part_01_path]",
        "https://frameio-uploads-production.s3-accelerate.amazonaws.com/parts/[part_02_path]"
    ],
    ...
}
```





此时，我们仅告知了 Frame.io 我们上传文件的意图；还没有传输任何实际文件数据。如果您检查项目中设备的文件夹，将看到处于“上传中”状态的占位符资产。

`upload_urls` 字段包含我们将上传文件分片的 URL。对于我们的测试文件，我们应该收到两个上传 URL。

## 步骤 2：将文件分为分片





响应包含多个上传 URL。在上传到 Frame.io 时，我们将文件分为分片，然后单独上传，这可以提供几项好处：




* **提高可靠性**：如果一个分片失败，我们无需重新启动整个上传
* **加快上传速度**：我们可以并行上传多个分片（在[高级上传指南](./how-to-advanced-uploads)中有所介绍）




要确定最佳分片大小，请使用以下公式：





**`Python`**

```python title="Python"
# We use math.ceil() to ensure we get the upper bound in the division
chunk_size = math.ceil(float(file.size) / float(len(response.upload_urls)))
```





对于我们的示例文件，计算结果为：





**`Python`**

```python title="Python"
math.ceil(21136250 / 2)
# 10568125
```

这意味着每个分片应为 10,568,125 个字节。分片大小通常以约 25 MB 为目标，确切计算在[高级上传指南](./how-to-advanced-uploads)中有所介绍。
<Info title="最后一个分片大小">
  由于文件大小很少能被整除，最后一个分片可能小于计算的 `chunk_size`。您的实施应该在读取文件分片时考虑到这一点。
</Info>
 在此演示中，我们将使用 [head](https://man7.org/linux/man-pages/man1/head.1.html) 和 [tail](https://man7.org/linux/man-pages/man1/tail.1.html) 命令来提取文件分片。

## 步骤 3：上传分片





上传第一个分片：





```shell
head -c 10568125 ~/Downloads/C2C_TEST_CLIP.mp4 | \
curl -X PUT https://frameio-uploads-production.s3-accelerate.amazonaws.com/parts/[part_01_path] \
        --include \
        --header 'content-type: video/mp4' \
        --header 'x-amz-acl: private' \
        --data-binary @-
```




<Info title="命令语法">
  `--data-binary @-` 参数指示 `curl` 使用来自 stdin 的原始数据（来自 `head` 命令）。
</Info>


该请求需要以下标头：

`content-type`：创建资产 `x-amz-acl` 时使用的相同 MIME 类型值：对于 AWS S3 权限，始终设置为 `private`

成功上传返回：





```text
HTTP/1.1 100 Continue

HTTP/1.1 200 OK
...
```





同样，上传第二个分片：





```shell
tail -c 10568125 ~/Downloads/C2C_TEST_CLIP.mp4 | \
curl -X PUT https://frameio-uploads-production.s3-accelerate.amazonaws.com/parts/[part_02_path] \
        --include \
        --header 'content-type: video/mp4' \
        --header 'x-amz-acl: private' \
        --data-binary @-
```





两个分片都上传完后，您的资产应可在 Frame.io 中播放！🎉




<Warning title="上传错误">
  在上传分片时，您是在将数据直接发送到 AWS S3，而不是 Frame.io 的 API。错误响应将遵循 AWS S3 格式，而不是标准的 Frame.io 错误。我们将在[错误处理指南](/camera-to-cloud/how-to-handle-errors)中介绍如何处理 S3 错误。
</Warning>

<Info title="分片顺序">
  


虽然从概念上来说按顺序上传数据分片更简单，但实际上可以按任意顺序上传。无论上传序列如何，系统都会正确组装它们。



</Info>


## 整合所有内容





以下是一个简化的、类似 Python 的伪代码示例，呈现了完整的上传过程：





**`Python`**

```python title="Python"
file = open("~/Downloads/C2C_TEST_CLIP.mp4")
mimetype = mimetypes.for_file("~/Downloads/C2C_TEST_CLIP.mp4")[0]
created_at = time.ctime(file.stat.ST_CTIME)

asset = c2c.asset_create(
    name="C2C_TEST_CLIP.mp4", 
    filetype=mimetype, 
    filesize=file.size,
    offset=datetime.now() - created_at,
    channel=0,
)

chunk_size = math.ceil(float(file.size) / float(len(asset.upload_urls)))

for chunk_url in asset.upload_urls:
   chunk = file.read(bytes=chunk_size)
   c2c.upload_chunk(chunk, chunk_url, mimetype)
```

此示例演示了基本流程，不包含错误处理或并行上传，这些内容将在[错误处理](/camera-to-cloud/how-to-handle-errors)和[高级上传](./how-to-advanced-uploads)指南中进行介绍。

## 后续步骤

恭喜您成功将第一个资产上传到了 Frame.io！[高级上传指南](./how-to-advanced-uploads)将介绍更复杂的技术和可随时投产的实施要求。我们鼓励您联系我们的团队咨询任何问题，并继续阅读[实时上传指南](./how-to-upload-realtime)，了解如何一边创建资产一边进行上传。