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,确保浏览器在页面内直接播放视频,而非触发下载弹窗。
前端验证事项
- 确认
api_url_name拼接后的请求地址正确,可通过浏览器开发者工具Network标签查看视频请求状态码(正常为200或206)。 - 检查视频文件是否为标准MP4格式(H.264编码),非标准编码的MP4可能无法被浏览器识别。
- 若存在跨域问题,需在Django中配置CORS(可使用
django-cors-headers库)。
内容的提问来源于stack exchange,提问作者zippy
相关产品推荐
相关产品推荐

