You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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)

关键注意事项

  1. MIME类型一致性:录制时用的是video/webm;codecs=vp9,opus,上传时Blob的类型要对应,后端会自动保存到documents/videointerviews路径(模型中upload_to已配置)。
  2. CSRF令牌验证:必须在请求头中携带X-CSRFToken,否则Django会拒绝请求。
  3. 文件名唯一性:用用户ID+时间戳命名,避免不同用户的视频文件重名覆盖。
  4. 文件大小限制:可以在Django配置文件中设置FILE_UPLOAD_MAX_MEMORY_SIZE调整允许上传的最大文件大小。

内容的提问来源于stack exchange,提问作者Oriza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 06:27:04