在 Vue 项目中实现视频的断点续传功能,需要结合前端技术处理文件切片、存储上传状态、恢复上传任务以及与后端接口协作。以下是实现前端视频断点续传的基本步骤和关键点:
步骤一:用户选择视频文件
1.使用 HTML5 的 元素: 创建一个文件输入框,允许用户选择视频文件。
<input type="file" accept="video/*" @change="onVideoSelected">
2.处理文件选择事件: 在 Vue 组件的方法中处理 onVideoSelected 事件,获取用户选择的 File 对象。
methods: {
onVideoSelected(event) {
this.selectedVideo = event.target.files[0];
// 进行后续的文件切片操作
},
},
步骤二:文件切片
1.确定切片大小: 根据实际需求和服务器限制设定合理的切片大小(例如,每片5MB)。
2.使用 Blob.slice() 方法: 对选定的视频文件进行切片处理,生成一系列 Blob 对象。
const CHUNK_SIZE = 5 * 1024 * 1024; // 5MB
const totalChunks = Math.ceil(this.selectedVideo.size / CHUNK_SIZE);
this.chunkList = [];
for (let i = 0; i < totalChunks; i++) {
const start = i * CHUNK_SIZE;
const end = Math.min(start + CHUNK_SIZE, this.selectedVideo.size);
const chunk = this.selectedVideo.slice(start, end);
this.chunkList.push(chunk);
}
步骤三:管理上传状态
1.创建上传状态对象: 为每个切片创建一个包含id(切片索引)、status(上传状态)、progress(上传进度)、response(后端响应数据)等属性的对象,用于跟踪上传状态。
this.uploadStatusList = this.chunkList.map((_, index) => ({
id: index,
status: 'pending', // 'pending', 'uploading', 'success', 'error'
progress: 0,
response: null,
}));
步骤四:上传切片
1.定义上传方法: 使用 fetch、axios 或其他 HTTP 请求库发送分片到后端接口。在请求中携带必要的头部信息(如 Content-Range),并监听上传进度以便更新状态。
async uploadChunk(chunk, chunkIndex) {
const url = 'https://your-backend-api/upload/chunk';
const headers = new Headers({
'Content-Type': 'application/octet-stream',
'Content-Length': chunk.size,
'Content-Range': `bytes ${chunkIndex * CHUNK_SIZE}-${(chunkIndex + 1) * CHUNK_SIZE - 1}/${this.selectedVideo.size}`,
});
try {
const response = await fetch(url, {
method: 'POST',
headers,
body: chunk,
});
if (!response.ok) {
throw new Error('Upload failed');
}
const data = await response.json();
// 更新上传状态列表中的相应切片状态
this.updateChunkStatus(chunkIndex, 'success', data);
} catch (error) {
this.updateChunkStatus(chunkIndex, 'error', error.message);
}
},
2.启动上传任务: 可以使用 Promise.all、async/await 或者按一定速率逐个上传切片。确保在上传过程中能够暂停、恢复或取消上传。
async startUpload() {
for (const [index, chunk] of this.chunkList.entries()) {
await this.uploadChunk(chunk, index);
}
}
步骤五:断点续传支持
1.存储上传状态: 使用浏览器的 localStorage、IndexedDB 或者后端数据库持久化存储上传状态。这样即使用户关闭页面或刷新浏览器,也能恢复未完成的上传任务。
saveUploadStatus() {
localStorage.setItem('uploadStatusList', JSON.stringify(this.uploadStatusList));
}
loadUploadStatus() {
const storedStatus = localStorage.getItem('uploadStatusList');
if (storedStatus) {
this.uploadStatusList = JSON.parse(storedStatus);
}
}
2.恢复未完成的上传: 在组件挂载时加载存储的上传状态,并检查是否有未完成的上传任务。如果有,根据状态自动或提示用户继续上传。
async mounted() {
this.loadUploadStatus();
// 检查是否有未完成的上传任务
const incompleteChunks = this.uploadStatusList.filter(status => status.status !== 'success');
if (incompleteChunks.length > 0) {
// 自动或提示用户恢复上传
await this.resumeUpload(incompleteChunks);
}
}
async resumeUpload(incompleteChunks) {
// 重新发起未完成切片的上传请求,或者提供用户界面供用户选择恢复哪些切片
}
步骤六:与后端接口协作
1.后端接口设计: 设计并实现对应的后端接口,接收分片上传、合并切片、查询上传状态等功能。
a.分片上传接口:接收单个切片,返回上传结果(如是否成功、错误信息等)。
b.合并切片接口:当所有切片上传完毕后,调用此接口通知后端合并文件。
c.查询上传状态接口:用于前端查询某个文件的上传进度和状态。
2.实现合并逻辑: 在后端实现对已上传切片的合并逻辑,确保文件完整性和顺序正确。