开发网站版YouTube视频下载器:如何调出文件保存对话框?
网站版YouTube视频下载器触发保存对话框解决方案
ytdl-core是Node.js端的视频处理库,本身不具备触发浏览器保存对话框的能力——这个功能需要前端API配合实现。下面提供两种可行方案:
一、前后端结合方案(推荐,无跨域问题)
1. 后端接口实现(Node.js + Express)
用ytdl-core处理视频流,通过接口返回给前端,并设置正确的响应头:
const express = require('express'); const ytdl = require('ytdl-core'); const app = express(); // 处理跨域(如果前端和后端域名不同) app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET'); next(); }); app.get('/download', async (req, res) => { const videoUrl = req.query.url; if (!ytdl.validateURL(videoUrl)) { return res.status(400).send('无效的YouTube链接'); } const videoInfo = await ytdl.getInfo(videoUrl); // 选择最高画质的视频格式 const targetFormat = ytdl.chooseFormat(videoInfo.formats, { quality: 'highest' }); // 设置响应头,告知浏览器这是可下载文件 res.setHeader( 'Content-Disposition', `attachment; filename="${videoInfo.videoDetails.title.replace(/[<>:"/\\|?*]/g, '')}.${targetFormat.container}"` ); res.setHeader('Content-Type', targetFormat.mimeType); // 将视频流管道到响应 ytdl(videoUrl, { format: targetFormat }).pipe(res); }); app.listen(3000, () => console.log('后端服务运行在3000端口'));
2. 前端触发下载逻辑
通过fetch请求后端接口,接收Blob数据后,用<a>标签触发浏览器的保存对话框:
// 绑定到按钮点击事件(必须由用户主动触发,否则浏览器会阻止) document.getElementById('downloadBtn').addEventListener('click', async () => { const youtubeUrl = document.getElementById('videoUrlInput').value; if (!youtubeUrl) { alert('请输入YouTube视频链接'); return; } try { const response = await fetch(`http://localhost:3000/download?url=${encodeURIComponent(youtubeUrl)}`); if (!response.ok) throw new Error('下载请求失败'); const videoBlob = await response.blob(); const blobUrl = URL.createObjectURL(videoBlob); // 创建临时a标签触发下载 const downloadLink = document.createElement('a'); downloadLink.href = blobUrl; // 从后端响应头获取文件名,或自定义 const filename = response.headers.get('Content-Disposition').match(/filename="(.*)"/)[1]; downloadLink.download = filename; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); URL.revokeObjectURL(blobUrl); // 释放内存资源 } catch (err) { console.error(err); alert('下载失败,请检查链接是否有效'); } });
二、纯前端尝试方案(存在跨域风险)
由于浏览器CORS政策限制,直接在前端调用ytdl-core大概率会触发跨域错误,仅作参考:
// 需先通过browserify/webpack将ytdl-core打包为前端可用模块 async function downloadVideoFrontend(youtubeUrl) { try { const videoInfo = await ytdl.getInfo(youtubeUrl); const targetFormat = ytdl.chooseFormat(videoInfo.formats, { quality: 'highest' }); // 直接请求视频链接可能触发CORS错误 const response = await fetch(targetFormat.url); const videoBlob = await response.blob(); const blobUrl = URL.createObjectURL(videoBlob); const downloadLink = document.createElement('a'); downloadLink.href = blobUrl; downloadLink.download = `${videoInfo.videoDetails.title.replace(/[<>:"/\\|?*]/g, '')}.${targetFormat.container}`; downloadLink.click(); URL.revokeObjectURL(blobUrl); } catch (err) { console.error('跨域错误或链接无效,请使用前后端方案'); } }
关键注意事项
- 必须通过用户主动触发的事件(如按钮点击)调用下载逻辑,否则会被浏览器拦截。
- 文件名需过滤特殊字符(如
<>:"/\|?*),避免保存时出错。 - 可通过ytdl-core的
chooseFormat方法自定义视频质量、格式(如仅选mp4格式)。
内容的提问来源于stack exchange,提问作者starlight
相关产品推荐
相关产品推荐

