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

Django+React环境下FileResponse返回MP4视频前端无法显示求助

Django返回MP4视频给React前端的解决方案

问题背景

在React+Django架构中,尝试用FileResponse返回MP4视频响应,但前端<video>标签无法正常加载视频。视频存储路径为运行时动态获取的LOGS_FOLDER_PATH,无法配置为Django静态资源路径。

原Django视图代码

@csrf_exempt
def get_video(request):
    view_logger.info("Fetching video")
    try:
        if not LOGS_FOLDER_PATH:
            view_logger.warning("LOGS FOLDER PATH not present")
            return HttpResponseNotFound("Logs folder path not set.")

        videos_path = os.path.join(LOGS_FOLDER_PATH, "videos")
        if not os.path.exists(videos_path):
            return HttpResponseNotFound("Videos folder does not exist.")

        videos_list = os.listdir(videos_path)
        if not videos_list:
            return HttpResponseNotFound("No videos found.")

        video_path = os.path.join(videos_path, videos_list[0])
        view_logger.info(f"Video path:- {video_path}")
        video_response = FileResponse(
            open(video_path, 'rb'),
        )
        view_logger.info(f"\n\n\n{video_response}")
        return video_response

    except Exception as error:
        view_logger.error(f"Error fetching terminal video. Error: {error}")
        return JsonResponse({'error': 'Internal server error'}, status=500)

原React组件代码

import React from "react";
import "./CSS/VideoDisplay.css";

const VideoDisplay = ({ api_url_name }) => {
  return (
    <div className="video-display-div">
      <video width="100%" controls aria-label="video">
        <source src={`${api_url_name}/api/dashboard/get-video/`} type="video/mp4" />
        Your browser does not support the video tag.
      </video>
    </div>
  );
};

export default VideoDisplay;

核心问题分析

  • 缺少正确的HTTP头:FileResponse默认未设置Content-Type为video/mp4,浏览器无法识别响应内容类型。
  • 不支持范围请求:浏览器加载视频时会发送Range请求头分段获取内容,默认FileResponse不处理该请求,导致视频无法播放。

修改后的Django视图代码

@csrf_exempt
def get_video(request):
    view_logger.info("Fetching video")
    try:
        if not LOGS_FOLDER_PATH:
            view_logger.warning("LOGS FOLDER PATH not present")
            return HttpResponseNotFound("Logs folder path not set.")

        videos_path = os.path.join(LOGS_FOLDER_PATH, "videos")
        if not os.path.exists(videos_path):
            return HttpResponseNotFound("Videos folder does not exist.")

        videos_list = os.listdir(videos_path)
        if not videos_list:
            return HttpResponseNotFound("No videos found.")

        video_path = os.path.join(videos_path, videos_list[0])
        view_logger.info(f"Video path:- {video_path}")

        file_size = os.path.getsize(video_path)
        range_header = request.META.get('HTTP_RANGE', '')
        
        if range_header:
            # 处理浏览器分段请求
            range_part = range_header.split('=')[1]
            start_str, end_str = range_part.split('-')
            start = int(start_str) if start_str else 0
            end = int(end_str) if end_str else file_size - 1
            length = end - start + 1

            video_file = open(video_path, 'rb')
            video_file.seek(start)
            response = HttpResponse(
                video_file.read(length),
                status=206,  # 分段响应状态码
                content_type='video/mp4'
            )
            response['Content-Range'] = f'bytes {start}-{end}/{file_size}'
            response['Content-Length'] = str(length)
        else:
            # 返回完整视频文件
            response = FileResponse(
                open(video_path, 'rb'),
                content_type='video/mp4'
            )
            response['Content-Length'] = str(file_size)
        
        # 设置浏览器直接播放而非下载
        response['Content-Disposition'] = 'inline; filename="video.mp4"'
        return response

    except Exception as error:
        view_logger.error(f"Error fetching terminal video. Error: {error}")
        return JsonResponse({'error': 'Internal server error'}, status=500)

代码说明

  • Content-Type设置:明确指定content_type='video/mp4',让浏览器识别响应为MP4视频格式。
  • 范围请求处理:解析HTTP_RANGE头,返回对应分段内容,设置206状态码及Content-Range头,满足浏览器分段加载需求。
  • Content-Disposition:设置为inline,确保浏览器在页面内直接播放视频,而非触发下载弹窗。

前端验证事项

  1. 确认api_url_name拼接后的请求地址正确,可通过浏览器开发者工具Network标签查看视频请求状态码(正常为200或206)。
  2. 检查视频文件是否为标准MP4格式(H.264编码),非标准编码的MP4可能无法被浏览器识别。
  3. 若存在跨域问题,需在Django中配置CORS(可使用django-cors-headers库)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 03:24:53