> This page is for 平台, version V4 (default).
> For other versions, use one of these documentation indexes:
> - V4 (default): https://next.developer.frame.io/platform/v4/llms.txt
> - V4 实验版: https://next.developer.frame.io/platform/v4-experimental/llms.txt
> - 旧版: https://next.developer.frame.io/platform/v2/llms.txt

> 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 V4 API 上传文件的完整流程。 其中涵盖了本地和远程上传的原始 API 请求和响应。

> **Info**
>
> **还在寻找 SDK 特定的指南？** 对于具有内置分片、重试和进度跟踪的上传实施，请参阅 [Python SDK 上传指南](./python-sdk-upload-guide)。

## 前提条件

在开始上传文件之前，请确保您已完成这些设置步骤：

#### Frame.io V4 帐户

您拥有通过 [Adobe Admin Console](https://adminconsole.adobe.com/) 管理的 Frame.io V4 帐户，或者已为您的帐户用户[切换到 Adobe 身份验证](https://help.frame.io/zh-CN/articles/11758018-connecting-to-adobe-authentication)

#### Adobe Developer Console 设置

您已登录 [Adobe Developer Console](https://developer.adobe.com/console) 并已将 Frame.io API 添加到一个新项目或现有项目中

#### 身份验证凭据

您已为您的项目生成了[适当的身份验证凭据](https://developer.adobe.com/frameio/guides/Authentication/)

#### 访问令牌

您已成功使用这些凭据生成访问令牌

## 选择您的上传方式

使用 Frame.io API 上传文件有两种方式：`创建文件（本地上传）`和`创建文件（远程上传）`。

#### 本地上传

当媒体可在您的应用程序本地访问时使用，类似于从桌面拖拽文件

#### 远程上传

当通过网络访问媒体时使用，例如通过与其他服务的集成

在本指南中，我们将从完成远程上传这一项比较简单的情况开始。

## 远程上传

要通过远程上传创建文件，请选择\*\*创建文件（远程上传）\*\*端点。 请求体需要文件名称及其来源 URL。

> **Warning**
>
> 远程上传目前有 **50 GB 的文件大小限制**。 对于超过 50 GB 的文件，请改用[本地上传](#local-upload)。

### 请求示例

```json
{ 
    "data": {
        "name": "my_file.jpg",
        "source_url": "https://upload.wikimedia.org/wikipedia/commons/e/e1/White_Pixel_1x1.jpg"
    }
}
```

### 响应示例

成功的请求将产生如下响应：

```json
{
    "data": {
        "id": "93e4079d-0a8a-4bf3-96cd-e6a03c465e5e",
        "name": "my_file.jpg",
        "status": "created",
        "type": "file",
        "file_size": 518,
        "updated_at": "2025-06-26T20:14:33.796116Z",
        "media_type": "image/jpeg",
        "parent_id": "2e426fe0-f965-4594-8b2b-b4dff1dc00ec",
        "project_id": "7e46e495-4444-4555-8649-bee4d391a997",
        "created_at": "2025-06-26T20:14:33.159489Z",
        "view_url": "https://next.frame.io/project/7e46e495-4444-4555-8649-bee4d391a997/view/93e4079d-0a8a-4bf3-96cd-e6a03c465e5e"
    },
    "links": {
        "status": "/v4/accounts/6f70f1bd-7e89-4a7e-b4d3-7e576585a181/files/93e4079d-0a8a-4bf3-96cd-e6a03c465e5e/status"
    }
}
```

## 本地上传

要通过本地上传创建文件，请选择\*\*创建文件（本地上传）\*\*端点。 请求体需要文件名称及其以字节为单位的文件大小。

### 请求示例

```json
{ 
    "data": {
        "name": "my_file.jpg",
        "file_size": 50645990
    }
}
```

### 响应示例

如果请求成功，会创建一个没有任何内容的占位符文件资源。 根据具体的文件大小，响应体将包含一个或多个 `upload_urls`。 以这个例子为例，我们将需要分多个分段管理此上传。

```json
{
    "data": {
        "id": "fa18ba7b-b3ee-4dd6-9b31-bd07e554241d",
        "name": "my_file.jpg",
        "status": "created",
        "type": "file",
        "file_size": 50645990,
        "updated_at": "2025-06-26T20:08:06.823170Z",
        "media_type": "image/jpeg",
        "parent_id": "2e426fe0-f965-4594-8b2b-b4dff1dc00ec",
        "project_id": "7e46e495-4444-4555-8649-bee4d391a997",
        "created_at": "2025-06-26T20:08:06.751313Z",
        "upload_urls": [
            {
                "size": 16881997,
                "url": "https://frameio-uploads-development.s3-accelerate.amazonaws.com/parts/fa18ba7b-b3ee-4dd6-9b31-bd07e554241d/part_1?..."
            },
            {
                "size": 16881997,
                "url": "https://frameio-uploads-development.s3-accelerate.amazonaws.com/parts/fa18ba7b-b3ee-4dd6-9b31-bd07e554241d/part_2?..."
            },
            {
                "size": 16881996,
                "url": "https://frameio-uploads-development.s3-accelerate.amazonaws.com/parts/fa18ba7b-b3ee-4dd6-9b31-bd07e554241d/part_3?..."
            }
        ],
        "view_url": "https://next.frame.io/project/7e46e495-4444-4555-8649-bee4d391a997/view/fa18ba7b-b3ee-4dd6-9b31-bd07e554241d"
    }
}
```

> **Warning**
>
> **重要的上传要求：**
>
> 发送后续上传请求时需要牢记以下重要详细信息：
>
> * HTTP 请求方法必须为 `PUT`
> * `x-amz-acl` 标头必须包含并设置为私密
> * `Content-Type` 标头必须与原始 **创建文件（本地上传）** 请求中指定的 `media_type` 匹配。 在将文件作为单独分段上传时也是如此。 在上述示例中，`media_type` 的值是 `image/jpeg`。 因此，`Content-Type` 的值也必须是 `image/jpeg`。

## 多分段上传

当给定文件产生多个上传 url 时，您需要将源文件拆分为分片，并为每个分片发出 PUT 请求。

> **Info**
>
> **推荐操作：**[Python SDK 上传指南](./python-sdk-upload-guide)涵盖使用 `FrameioUploader` 进行多分段上传，它可以开箱即用地处理分片、并行上传、重试和跟踪进度。

如果您需要手动实施上传（例如，在没有 SDK 的语言中，或者为了完全控制上传过程），下面的脚本展示了如何将文件分成多个分片，并使用预签名 URL 上传每个分片。

### Python 实施示例

**`多分段上传脚本`**

```python title="多分段上传脚本"
import requests
import math
from typing import List
from tqdm import tqdm  # For progress bar

def upload_file_in_chunks(file_path: str, upload_urls: list[str], content_type: str | None = None, chunk_size: int | None = None) -> bool:
    """
    Upload a file in chunks using presigned URLs.
    """
    try:
        # Auto-detect content type based on file extension
        if content_type is None:
            detected_content_type, _ = mimetypes.guess_type(file_path)
            content_type = detected_content_type # Default fallback

        print(f"Detected content type: {content_type}")

        # Get file size
        with open(file_path, 'rb') as f:
            f.seek(0, 2)  # Seek to end of file
            file_size = f.tell()

        # Calculate chunk size if not provided
        if chunk_size is None:
            chunk_size = math.ceil(file_size / len(upload_urls))

        print(f"File size: {file_size} bytes")
        print(f"Chunk size: {chunk_size} bytes")
        print(f"Number of chunks: {len(upload_urls)}")

        # Upload each chunk
        with open(file_path, 'rb') as f:
            with tqdm(total=len(upload_urls), desc="Uploading chunks") as pbar:
                for i, url in enumerate(upload_urls):
                    start_byte = i * chunk_size
                    end_byte = min(start_byte + chunk_size, file_size)

                    # Read chunk from file
                    f.seek(start_byte)
                    chunk = f.read(end_byte - start_byte)

                    print(f"Uploading chunk {i+1}: {len(chunk)} bytes")

                    # Upload chunk with minimal headers matching the signature
                    response = requests.put(
                        url,
                        data=chunk,
                        headers={
                            'content-type': content_type,
                            'x-amz-acl': 'private'
                        }
                    )

                    if response.status_code != 200:
                        print(f"Failed to upload chunk {i+1}. Status code: {response.status_code}")
                        print(f"Response text: {response.text}")
                        print(f"Response headers: {dict(response.headers)}")
                        return False
                    else:
                        print(f"Chunk {i+1} uploaded successfully!")

                    pbar.update(1)

        return True

    except Exception as e:
        print(f"Error during upload: {str(e)}")
        return False

# Example usage
if __name__ == "__main__":
    # Replace these with your actual values
    file_path = "/Users/MyComputer/local_upload/sample.jpg"  # Path to your file
    upload_urls = [
        "https://frameio-uploads-development.s3-accelerate.amazonaws.com/parts/fa18ba7b-b3ee-4dd6-9b31-bd07e554241d/part_1?...",
        "https://frameio-uploads-development.s3-accelerate.amazonaws.com/parts/fa18ba7b-b3ee-4dd6-9b31-bd07e554241d/part_2?...",
        "https://frameio-uploads-development.s3-accelerate.amazonaws.com/parts/fa18ba7b-b3ee-4dd6-9b31-bd07e554241d/part_3?..."
    ]
    content_type = "image/jpeg"

    print("Starting file upload...")
    success = upload_file_in_chunks(file_path, upload_urls, content_type)

    if success:
        print("File upload completed successfully!")
    else:
        print("File upload failed!")
```

## 上传流程总结

#### 选择上传方法

决定是远程上传（通过 URL 访问文件）还是本地上传（系统上的文件）

#### 创建文件请求

发出初始请求来使用所需元数据创建文件资源

#### 处理上传 URL

对于本地上传，处理返回的 upload\_urls（单个或多个分段）

#### 上传文件内容

使用带有适当标头的 PUT 请求将文件内容上传到提供的 URL

#### 验证上传

检查文件状态以确认上传和处理是否成功

> **Info**
>
> **后续步骤**：文件上传后，您可以使用返回的文件 ID 来添加评论、创建共享项或使用 Frame.io V4 API 执行其他操作。