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

Bootcamp毕业项目:React.JS+Django音视频上传功能实现咨询

音视频上传功能实现方案建议(React + Django)

前端实现(React)

  • 文件选择与基础校验
    可以用原生的<input type="file" accept="audio/*,video/*" multiple />实现基础文件选择,也可以用react-dropzone库快速开发拖拽上传功能。前端先做一层校验:通过accept属性限制文件类型,通过file.size限制文件大小(比如视频不超100MB、音频不超50MB),减少无效请求。
  • 上传进度与状态反馈
    用Fetch API或XMLHttpRequest发送请求时,监听进度事件实现进度条。比如用XHR的onprogress事件实时获取上传进度,给用户展示“上传中”“上传成功”“上传失败”的状态提示。
  • 请求封装示例
    const handleUpload = async (file) => {
      const formData = new FormData();
      formData.append('media_file', file);
      
      try {
        const response = await fetch('/api/upload-media/', {
          method: 'POST',
          headers: {
            'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
          },
          body: formData
        });
        const data = await response.json();
        console.log('上传成功', data);
      } catch (error) {
        console.error('上传失败', error);
      }
    };
    
    注意:不要手动设置Content-Type,浏览器会自动根据FormData生成正确的请求头。

后端实现(Django)

  • 基础配置
    在settings.py中配置媒体文件存储路径:
    MEDIA_ROOT = BASE_DIR / 'media'
    MEDIA_URL = '/media/'
    
    开发阶段在urls.py中添加媒体文件的访问路由:
    from django.conf import settings
    from django.conf.urls.static import static
    
    urlpatterns = [
        # 其他业务路由
    ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    
  • 模型设计(可选)
    如果需要存储文件元数据(上传者、类型、时间等),定义如下模型:
    from django.db import models
    from django.contrib.auth.models import User
    
    class MediaFile(models.Model):
        FILE_TYPE_CHOICES = (
            ('audio', '音频'),
            ('video', '视频'),
        )
        file = models.FileField(upload_to='media_files/%Y/%m/%d/')
        file_type = models.CharField(max_length=10, choices=FILE_TYPE_CHOICES)
        uploaded_at = models.DateTimeField(auto_now_add=True)
        uploader = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
    
        def save(self, *args, **kwargs):
            # 自动判断文件类型
            ext = self.file.name.split('.')[-1].lower()
            if ext in ['mp3', 'wav', 'flac']:
                self.file_type = 'audio'
            elif ext in ['mp4', 'avi', 'mov']:
                self.file_type = 'video'
            super().save(*args, **kwargs)
    
  • 上传视图实现
    编写处理上传的视图,做后端二次校验并保存文件:
    from django.http import JsonResponse
    from .models import MediaFile
    import os
    
    def upload_media(request):
        if request.method == 'POST' and request.FILES.get('media_file'):
            media_file = request.FILES['media_file']
            # 校验文件大小
            if media_file.size > 100 * 1024 * 1024:
                return JsonResponse({'error': '文件大小超过100MB限制'}, status=400)
            # 校验文件扩展名
            allowed_exts = {'mp3', 'wav', 'flac', 'mp4', 'avi', 'mov'}
            ext = media_file.name.split('.')[-1].lower()
            if ext not in allowed_exts:
                return JsonResponse({'error': '不支持该文件类型'}, status=400)
            # 保存到模型
            obj = MediaFile.objects.create(file=media_file, uploader=request.user if request.user.is_authenticated else None)
            return JsonResponse({
                'success': True,
                'file_url': obj.file.url,
                'file_id': obj.id
            })
        return JsonResponse({'error': '无效请求'}, status=400)
    
    在urls.py中挂载视图:
    from .views import upload_media
    
    urlpatterns = [
        path('api/upload-media/', upload_media, name='upload-media'),
        # 其他路由
    ]
    

关键优化与注意事项

  • 大文件分片上传:如果要支持GB级视频,建议实现分片上传。前端把文件切成5MB左右的小块,依次上传到后端,后端接收后拼接成完整文件,避免单次请求超时。
  • 文件转码:如果需要统一格式(比如转成MP4/MP3),可以集成FFmpeg工具,在文件保存后调用FFmpeg命令转码,转码完成后替换原文件或生成新的转码文件。
  • 权限控制:如果是用户专属上传,要在视图中验证用户身份(Session或JWT),确保只有登录用户能上传,且只能访问自己的文件。
  • 生产环境配置:生产环境不要用Django自带的本地存储,建议配置云存储(如OSS、S3),通过django-storages库对接,提升文件访问性能和可靠性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 11:35:38