如何用JavaScript和Django将录制视频保存至文件系统与数据库?
解决Django中视频录制后自动上传服务器并入库的问题
核心思路
把原有的本地下载逻辑替换为通过AJAX将录制好的视频Blob直接上传到Django后端,后端接收后自动保存到指定路径并写入数据库,跳过手动下载再上传的步骤。
步骤1:修改JavaScript上传逻辑
替换downloadButton的点击事件,取消本地下载,改为构造表单数据发送到后端:
downloadButton.addEventListener('click', async () => { // 构造录制好的视频Blob(保持和录制一致的MIME类型) const blob = new Blob(recordedBlobs, {type: 'video/webm'}); // 创建FormData对象模拟表单上传 const formData = new FormData(); // 从页面隐藏域获取用户ID,生成唯一文件名(避免重复) const userId = document.getElementById('user-id').value; const fileName = `${userId}_${Date.now()}.webm`; formData.append('document', blob, fileName); // 获取页面的CSRF令牌,Django必须验证这个 const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value; try { const response = await fetch(window.location.href, { method: 'POST', headers: { 'X-CSRFToken': csrfToken, }, body: formData }); if (response.ok) { alert('视频上传成功!'); window.location.href = '/mpa/main'; } else { const errorText = await response.text(); throw new Error(errorText); } } catch (e) { errorMsgElement.innerHTML = `上传失败:${e.message}`; console.error('上传错误:', e); } });
同时在HTML中添加用户ID的隐藏域(放在容器或表单内均可):
<input type="hidden" id="user-id" value="{{ request.user.id }}">
步骤2:调整Django视图处理AJAX上传
修改video_interview视图,兼容AJAX文件上传请求,同时保留原表单提交功能:
from django.http import JsonResponse @login_required def video_interview(request, company_uuid, position_id, position_slug): ruser = request.user.id position = Position.objects.filter(id=position_id, position_slug=position_slug).first() if request.method == 'POST': # 处理AJAX视频上传请求 if 'document' in request.FILES: video_obj = VideoInterview() video_obj.candidate = request.user video_obj.document = request.FILES['document'] video_obj.description = f"{request.user.username} 的面试视频" # 设置默认描述 video_obj.save() # 针对AJAX请求返回JSON响应,普通请求直接跳转 if request.headers.get('X-Requested-With') == 'XMLHttpRequest': return JsonResponse({'status': 'success'}, status=200) else: return redirect('/mpa/main') # 处理原表单提交逻辑 else: form = VideoInterviewUploadForm(request.POST, request.FILES) form.instance.candidate = request.user if form.is_valid(): form.save() return redirect('/mpa/main') else: form = VideoInterviewUploadForm() context = { 'form': form, 'position': position, } return render(request, 'myway/video_interview.html', context)
关键注意事项
- MIME类型一致性:录制时用的是
video/webm;codecs=vp9,opus,上传时Blob的类型要对应,后端会自动保存到documents/videointerviews路径(模型中upload_to已配置)。 - CSRF令牌验证:必须在请求头中携带
X-CSRFToken,否则Django会拒绝请求。 - 文件名唯一性:用用户ID+时间戳命名,避免不同用户的视频文件重名覆盖。
- 文件大小限制:可以在Django配置文件中设置
FILE_UPLOAD_MAX_MEMORY_SIZE调整允许上传的最大文件大小。
内容的提问来源于stack exchange,提问作者Oriza
相关产品推荐
相关产品推荐

