# Stream 模式
常用工作流、全栈流程和最佳实践。
## React Stream 播放器
`npm install @cloudflare/stream-react`
tsx
import { Stream } from '@cloudflare/stream-react';
export function VideoPlayer({ videoId, token }: { videoId: string; token?: string }) {
return ;
}
## 全栈上传流程
**后端 API (Workers/Pages)**
typescript
import Cloudflare from 'cloudflare';
export default {
async fetch(request: Request, env: Env): Promise {
const { videoName } = await request.json();
const client = new Cloudflare({ apiToken: env.CF_API_TOKEN });
const { uploadURL, uid } = await client.stream.directUpload.create({
account_id: env.CF_ACCOUNT_ID,
maxDurationSeconds: 3600,
requireSignedURLs: true,
meta: { name: videoName }
});
return Response.json({ uploadURL, uid });
}
};
**前端组件**
tsx
import { useState } from 'react';
export function VideoUploader() {
const [uploading, setUploading] = useState(false);
const [progress, setProgress] = useState(0);
async function handleUpload(file: File) {
setUploading(true);
const { uploadURL, uid } = await fetch('/api/upload-url', {
method: 'POST',
body: JSON.stringify({ videoName: file.name })
}).then(r => r.json());
const xhr = new XMLHttpRequest();
xhr.upload.onprogress = (e) => setProgress((e.loaded / e.total) * 100);
xhr.onload = () => { setUploading(false); window.location.href = `/videos/${uid}`; };
xhr.open('POST', uploadURL);
const formData = new FormData();
formData.append('file', file);
xhr.send(formData);
}
return (
e.target.files?.[0] && handleUpload(e.target.files[0])} disabled={uploading} />
{uploading &&
}
);
}
## TUS 断点续传
适用于大文件 (>500MB)。`npm install tus-js-client`
typescript
import * as tus from 'tus-js-client';
async function uploadWithTUS(file: File, uploadURL: string, onProgress?: (pct: number) => void) {
return new Promise((resolve, reject) => {
const upload = new tus.Upload(file, {
endpoint: uploadURL,
retryDelays: [0, 3000, 5000, 10000, 20000],
chunkSize: 50 * 1024 * 1024,
metadata: { filename: file.name, filetype: file.type },
onErro