跳转到内容
搜索文档

创作者直接上传

最后更新 查看 MarkdownAgent 设置

创作者直接上传(Direct creator uploads)让您的终端用户直接向 Cloudflare Stream 上传视频,而无需向客户端暴露 API token。您可以使用基本 POST 请求tus 协议实现创作者直接上传。使用以下图表决定使用哪种方法:

flowchart LR
accTitle: 创作者直接上传决策流程
accDescr: 根据文件大小和连接可靠性选择基本 POST 上传或 tus 协议的决策流程

A{视频是否超过 200 MB?}
A -->|是| B[必须使用 tus 协议]:::link
A -->|否| C{终端用户是否有稳定连接?}
C -->|是| D[建议使用基本 POST]:::link
C -->|否| E[tus 协议可选,但建议使用]:::link

classDef link text-decoration:underline,color:#F38020

click B "#direct-creator-uploads-with-tus-protocol" "了解 tus 协议"
click D "#basic-post-request" "查看基本 POST 说明"
click E "#direct-creator-uploads-with-tus-protocol" "了解 tus 协议"

基本 POST 请求

如果终端用户的视频小于 200 MB 且连接稳定,建议使用此方法。如果终端用户的连接不稳定,建议使用 tus 协议

要启用 POST 请求的创作者直接上传:

步骤 1:生成唯一的一次性上传 URL

使用 Direct upload API 生成唯一的一次性上传 URL。

生成上传sh
curl https://api.cloudflare.com/client/v4/accounts/{account_id}/stream/direct_upload \
--header 'Authorization: Bearer <API_TOKEN>' \
 --data '{
    "maxDurationSeconds": 3600
 }'
{
	"result": {
		"uploadURL": "https://upload.videodelivery.net/f65014bc6ff5419ea86e7972a047ba22",
		"uid": "f65014bc6ff5419ea86e7972a047ba22"
	},
	"success": true,
	"errors": [],
	"messages": []
}

请参阅完整的 Stream REST API 和 SDK 参考,了解如何从外部应用程序使用 REST API,以及适用于外部 TypeScript、Python 或 Go 应用的预生成 SDK。

export default {
	async fetch(request, env, ctx): Promise<Response> {
		const directUpload = await env.STREAM.createDirectUpload({
			maxDurationSeconds: 3600,
		});

		return new Response(JSON.stringify(directUpload));
	},
} satisfies ExportedHandler<{ STREAM: StreamBinding }>;
{
	"$schema": "node_modules/wrangler/config-schema.json",
	"name": "<ENTER_WORKER_NAME>",
	"main": "src/index.ts",
	"compatibility_date": "$today",
	"observability": {
		"enabled": true
	},
	"stream": {
		"binding": "STREAM"
	}
}

请参阅完整的 Workers Stream 绑定 API 参考

步骤 2:将视频上传到一次性 URL

使用上一步中的 uploadURL,用户可以上传大小限制为 200 MB 的视频文件。请参阅以下示例请求。

将视频上传到唯一的一次性上传 URLbash
curl --request POST \
  --form file=@/Users/mickie/Downloads/example_video.mp4 \
  https://upload.videodelivery.net/f65014bc6ff5419ea86e7972a047ba22

成功上传返回 200 HTTP 状态码响应。如果上传不符合创建时定义的上传约束或大小超过 200 MB,响应将返回 4xx HTTP 状态码。

使用 tus 协议的创作者直接上传

如果终端用户的视频超过 200 MB,必须使用 tus 协议。即使文件小于 200 MB,如果终端用户的连接可能不稳定,Cloudflare 也建议使用 tus 协议,因为它支持断点续传。有关 tus 协议要求、其他客户端示例和上传选项的详细信息,请参阅可恢复和大文件 (tus)

以下图表展示了此过程两个步骤的交互方式:

sequenceDiagram
accTitle: 使用 tus 的创作者直接上传时序图
accDescr: 展示后端配置 tus 上传 URL 和终端用户直接上传到 Stream 的两步流程

participant U as 终端用户
participant B as 您的后端
participant S as Cloudflare Stream

U->>B: 发起上传请求
B->>S: 请求 tus 上传 URL(已认证)
S->>B: 返回一次性上传 URL
B->>U: 返回一次性上传 URL
U->>S: 使用 tus 直接上传视频

步骤 1:后端配置一次性上传 URL

以下示例展示如何构建 Worker,向终端用户返回一次性上传 URL。对于 tus 协议上传,后端必须传递 Tus-ResumableUpload-LengthUpload-Metadata 头。一次性上传 URL 在响应的 Location 头中返回,而非响应体中。

tus API 端点示例javascript
export async function onRequest(context) {
	const { request, env } = context;
	const { CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API_TOKEN } = env;
	const endpoint = `https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/stream?direct_user=true`;

	const response = await fetch(endpoint, {
		method: "POST",
		headers: {
			Authorization: `bearer ${CLOUDFLARE_API_TOKEN}`,
			"Tus-Resumable": "1.0.0",
			"Upload-Length": request.headers.get("Upload-Length"),
			"Upload-Metadata": request.headers.get("Upload-Metadata"),
		},
	});

	const destination = response.headers.get("Location");

	return new Response(null, {
		headers: {
			"Access-Control-Expose-Headers": "Location",
			"Access-Control-Allow-Headers": "*",
			"Access-Control-Allow-Origin": "*",
			Location: destination,
		},
	});
}

步骤 2:终端用户的客户端直接上传到 Stream

在 tus 客户端中直接使用后端端点。请参阅以下完整示例,演示如何将步骤 1 的后端与 uppy tus 客户端配合使用。

使用 uppy tus 客户端上传视频html
<html>
	<head>
		<link
			href="https://releases.transloadit.com/uppy/v3.0.1/uppy.min.css"
			rel="stylesheet"
		/>
	</head>
	<body>
		<div id="drag-drop-area" style="height: 300px"></div>
		<div class="for-ProgressBar"></div>
		<button class="upload-button" style="font-size: 30px; margin: 20px">
			Upload
		</button>
		<div class="uploaded-files" style="margin-top: 50px">
			<ol></ol>
		</div>
		<script type="module">
			import {
				Uppy,
				Tus,
				DragDrop,
				ProgressBar,
			} from "https://releases.transloadit.com/uppy/v3.0.1/uppy.min.mjs";

			const uppy = new Uppy({ debug: true, autoProceed: true });

			const onUploadSuccess = (el) => (file, response) => {
				const li = document.createElement("li");
				const a = document.createElement("a");
				a.href = response.uploadURL;
				a.target = "_blank";
				a.appendChild(document.createTextNode(file.name));
				li.appendChild(a);

				document.querySelector(el).appendChild(li);
			};

			uppy
				.use(DragDrop, { target: "#drag-drop-area" })
				.use(Tus, {
					endpoint: "/api/get-upload-url",
					chunkSize: 150 * 1024 * 1024,
				})
				.use(ProgressBar, {
					target: ".for-ProgressBar",
					hideAfterFinish: false,
				})
				.on("upload-success", onUploadSuccess(".uploaded-files ol"));

			const uploadBtn = document.querySelector("button.upload-button");
			uploadBtn.addEventListener("click", () => uppy.upload());
		</script>
	</body>
</html>

有关使用 tus 和客户端代码示例的更多详情,请参阅可恢复和大文件 (tus)

Upload-Metadata 头语法

使用 tus 时,您可以应用与基本创作者直接上传相同的约束。为此,您必须在第一个请求(由上述 Worker 发出)的 Upload-Metadata 请求头中传递 expirymaxDurationSeconds。执行实际文件上传的后续请求将忽略 Upload-Metadata 值。

Upload-Metadata 头应包含键值对。键为文本,值应编码为 base64。用空格(而非等号)分隔键和值。要连接多个键值对,使用逗号且不加额外空格。

在以下示例中,Upload-Metadata 头指示 Stream 仅接受最大视频时长 10 分钟、在过期时间戳之前上传的视频,并将此视频设为私有:

'Upload-Metadata: maxDurationSeconds NjAw,requiresignedurls,expiry MjAyNC0wMi0yN1QwNzoyMDo1MFo='

NjAw 是 "600"(或 10 分钟)的 base64 编码值。

MjAyNC0wMi0yN1QwNzoyMDo1MFo= 是 "2024-02-27T07:20:50Z"(RFC3339 格式时间戳)的 base64 编码值

跟踪上传进度

创建唯一的一次性上传 URL 后,您应保留响应中返回的唯一标识符(uid)以跟踪用户的上传进度。

您可以通过以下方式跟踪上传进度:

这篇文档对您有帮助吗?