React Native调用Flask后端下载YouTube文件失败的解决方案咨询
解决方案:Flask后端优化 + React Native客户端下载实现
一、服务端优化方案
1. 修复路由参数问题
原路由直接将视频ID作为路径参数,易触发URL编码、特殊字符解析错误,改为查询参数更安全可靠。
2. 添加跨域支持
React Native请求后端会触发跨域,需为Flask添加CORS支持,避免请求被拦截。
3. 完善错误处理与资源清理
添加异常捕获逻辑避免服务崩溃;发送文件后自动清理临时文件,防止服务器磁盘占用过高。
修改后的服务端代码
先安装依赖:
pip install flask-cors
app.py:
from flask import Flask, send_file, request, jsonify from flask_cors import CORS import vid_request import os app = Flask(__name__) CORS(app) # 允许跨域请求,生产环境可配置指定域名 @app.route("/download") def download(): video_id = request.args.get("video_id") if not video_id: return jsonify({"error": "缺少video_id参数"}), 400 file_path = None try: file_path = vid_request.download(video_id, "tempDownloads") file_name = os.path.basename(file_path) # 指定MIME类型,确保客户端正确识别文件格式 return send_file( file_path, as_attachment=True, download_name=file_name, mimetype="audio/mp4" ) except Exception as e: return jsonify({"error": str(e)}), 500 finally: # 发送完成后删除临时文件 if file_path and os.path.exists(file_path): os.remove(file_path) if __name__ == "__main__": app.run(host="0.0.0.0", debug=True)
vid_request.py(优化流选择与错误处理):
import pytube def download(video_id, path): url = f"https://www.youtube.com/watch?v={video_id}" youtube_obj = pytube.YouTube(url) # 筛选最高质量的MP4音频流 audio_stream = youtube_obj.streams.filter(only_audio=True, file_extension="mp4") \ .order_by("abr").desc().first() if not audio_stream: raise Exception("该视频无可用音频流") return audio_stream.download(output_path=path)
二、React Native客户端下载实现
原生fetch不会自动处理文件下载,需手动将响应转为Blob,再写入本地文件系统。
1. 安装依赖
npm install react-native-fs # 或 yarn add react-native-fs
2. 客户端代码示例
import RNFS from 'react-native-fs'; const downloadYouTubeAudio = async (videoId) => { try { const response = await fetch(`http://192.168.0.12:5000/download?video_id=${videoId}`); if (!response.ok) { const errorRes = await response.json(); throw new Error(errorRes.error || '下载请求失败'); } // 将响应转为Blob格式 const blob = await response.blob(); // 从响应头提取文件名 const contentDisposition = response.headers.get('Content-Disposition'); let fileName = 'audio.mp4'; if (contentDisposition) { const nameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/); if (nameMatch?.[1]) { fileName = nameMatch[1].replace(/['"]/g, ''); } } // 保存到手机下载目录 const savePath = `${RNFS.DownloadDirectoryPath}/${fileName}`; // 将Blob转为Base64写入文件 const base64Data = await new Promise(resolve => { const reader = new FileReader(); reader.onloadend = () => resolve(reader.result.split(',')[1]); reader.readAsDataURL(blob); }); await RNFS.writeFile(savePath, base64Data, 'base64'); console.log(`文件已保存至: ${savePath}`); // 可在此添加用户提示,如Toast通知下载完成 } catch (err) { console.error('下载出错:', err.message); // 提示用户错误信息 } }; // 调用示例:downloadYouTubeAudio('目标视频ID');
三、关键注意事项
- 确保手机与服务器处于同一局域网,且服务器IP地址配置正确。
- Android需在
AndroidManifest.xml添加网络权限:<uses-permission android:name="android.permission.INTERNET" /> - iOS需允许HTTP请求,在
Info.plist中添加:<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict> - 定期更新
pytube:YouTube接口会频繁调整,执行pip install --upgrade pytube保持依赖最新。
内容的提问来源于stack exchange,提问作者giji676
相关产品推荐
相关产品推荐

