使用ytdl-core+Express下载YouTube视频失败问题排查求助
嘿,我帮你排查了下这段代码里的问题,主要是前端请求方式不对,加上缺少错误处理导致的无响应,咱们一步步来修复:
问题根源
- 你前端用了同步XMLHttpRequest(
req.open('get', ..., false)),这种方式会卡死浏览器主线程,而且浏览器不会自动识别响应里的Content-Disposition: attachment头,自然不会弹出下载窗口。 - 不管是前端还是后端,都没做错误处理——比如输入空链接、无效YouTube地址、下载失败时,完全没有提示,看起来就像“没反应”。
- 后端的
app.listen放在了路由定义之前,虽然Express允许这么做,但不符合最佳实践,容易搞混顺序。
修复后的完整代码
前端 script.js
把同步XHR换成更靠谱的触发方式:用隐藏的<a>标签发起请求,让浏览器自动处理下载逻辑,同时增加基础校验:
const confirmText = "Downloading videos from YouTube is against the YouTube Policy.\n" + "The only videos that you're allowed to download is your own."; function downloadVideo() { if (confirm(confirmText)) { const URLinput = document.getElementById("URL-input").value.trim(); // 先校验输入是否为空 if (!URLinput) { alert("请输入有效的YouTube链接!"); return; } // 创建隐藏a标签触发下载 const downloadLink = document.createElement('a'); // 用encodeURIComponent处理参数,避免特殊字符破坏请求 downloadLink.href = `/download?url=${encodeURIComponent(URLinput)}`; downloadLink.target = '_blank'; // 新开标签处理下载,不阻塞当前页面 document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); } }
后端 index.js
增加错误处理、URL校验,优化文件名,同时调整路由顺序:
const express = require('express'); const path = require('path'); const cors = require('cors'); const ytdl = require('ytdl-core'); const app = express(); // 中间件先加载 app.use(cors()); app.use(express.static("public")); // 定义路由 app.get('/', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'index.html')); }); app.get('/download', async (req, res) => { try { const urlInput = req.query.url; // 先校验URL是否合法 if (!urlInput || !ytdl.validateURL(urlInput)) { return res.status(400).send("无效的YouTube链接,请检查输入!"); } console.log('开始处理下载请求:', urlInput); // 获取视频标题作为下载文件名,清理非法字符 const videoInfo = await ytdl.getInfo(urlInput); const cleanTitle = videoInfo.videoDetails.title.replace(/[^\w\s-]/gi, ''); res.header('Content-Disposition', `attachment; filename="${cleanTitle}.mp4"`); // 创建下载流并监听错误 const videoStream = ytdl(urlInput, { format: 'mp4' }); videoStream.on('error', (err) => { console.error('下载出错:', err); res.status(500).send("视频下载失败,请稍后重试!"); }); // 把流pipe给响应 videoStream.pipe(res); } catch (err) { console.error('请求处理出错:', err); res.status(500).send("服务器内部错误,请稍后重试!"); } }); // 404页面路由 app.get('*', (req, res) => { res.sendFile(path.join(__dirname, 'public', '404.html')); }); // 最后启动服务器 app.listen(4000, () => { console.log('Server Works !!! At port 4000'); });
额外提醒
- 确保你已经安装了所有依赖:
npm install express cors ytdl-core - 记得定期更新
ytdl-core,因为YouTube的接口经常变,旧版本可能会失效:npm update ytdl-core - 你保留的合规提示很重要,一定要继续保留,避免违反YouTube的服务条款
内容的提问来源于stack exchange,提问作者Kodak3993
相关产品推荐
相关产品推荐

