Node.js视频下载完成后如何清空输入框中的URL内容?
如何在视频下载完成后清空输入框
问题描述
我开发了一款视频下载器,用户在客户端输入URL后点击下载按钮即可下载视频。目前视频能成功下载,但存在一个小问题:下载完成后输入框中的URL不会被清空。我曾尝试在客户端(EJS)添加事件监听器来清空输入框,但完全无效。我认为可能需要在服务器端向客户端发送下载完成的信号,以便事件监听器处理清空输入框的操作,但不清楚具体如何实现。
当前服务器端代码:
app.get('/download', async (req, res) => { try { const url = req.query.url; console.log(url); const options = { quality: '18', filter: format => format.container === 'mp4' && format.hasAudio && format.hasVideo, }; //Fetch Video ID metadata const videoId = await ytdl.getURLVideoID(url); console.log("Video ID fetched:", videoId); //Set the content dispositon header to trigger download res.attachment(`${videoId}.mp4`); //Download and pipe the video stream const videoStream = ytdl(url, options); videoStream.pipe(res); videoStream.on('finish', () => { console.log("Video is downloaded."); res.end(); }); } catch (err) { console.error(err); res.status(500).send("Internal server error"); } });
核心问题分析
直接通过表单提交或a标签触发GET下载请求时,浏览器会独立处理下载流,页面本身无法感知这个请求的完成状态——这就是你之前添加事件监听器无效的根源。要解决这个问题,需要通过JavaScript主动发起请求并监听完成事件,或者通过WebSocket让服务器主动通知客户端。
解决方案
方案一:使用Fetch API处理下载(轻量首选)
通过Fetch主动发起请求,手动处理下载流,完成后直接清空输入框:
客户端(EJS页面)代码修改
<input type="text" id="videoUrl" placeholder="输入视频URL"> <button id="downloadBtn">下载</button> <script> document.getElementById('downloadBtn').addEventListener('click', async () => { const urlInput = document.getElementById('videoUrl'); const videoUrl = urlInput.value.trim(); if (!videoUrl) return; try { // 发起下载请求,编码URL避免特殊字符出错 const response = await fetch(`/download?url=${encodeURIComponent(videoUrl)}`); if (!response.ok) throw new Error('下载请求失败'); // 将响应转为Blob,生成可下载链接 const blob = await response.blob(); const downloadUrl = URL.createObjectURL(blob); // 创建临时a标签触发浏览器下载 const a = document.createElement('a'); a.href = downloadUrl; // 从响应头解析文件名 const contentDisposition = response.headers.get('Content-Disposition'); const filename = contentDisposition?.match(/filename="?([^"]+)"?/)?.[1] || 'video.mp4'; a.download = filename; a.click(); // 清理临时URL对象 URL.revokeObjectURL(downloadUrl); // 下载完成后清空输入框 urlInput.value = ''; } catch (err) { console.error(err); alert('下载出错,请重试'); } }); </script>
服务器端调整
无需大改现有代码,保持原逻辑即可。如果需要优化,可以确保响应头返回正确的Content-Length(ytdl部分格式会自动携带),但不影响核心功能。
方案二:WebSocket实现服务器主动通知(复杂场景适用)
如果你的应用需要实时同步更多状态,可通过WebSocket让服务器主动告知客户端下载完成:
服务器端添加WebSocket支持(使用ws库)
const WebSocket = require('ws'); // 假设app是Express实例,需要传入HTTP服务器 const wss = new WebSocket.Server({ server: app.listen(3000) }); wss.on('connection', (ws) => { console.log('客户端已连接'); ws.on('close', () => console.log('客户端已断开')); }); // 修改/download接口的finish事件 videoStream.on('finish', () => { console.log("Video is downloaded."); // 向所有连接的客户端发送完成通知 wss.clients.forEach(client => { if (client.readyState === WebSocket.OPEN) { client.send(JSON.stringify({ type: 'downloadComplete', targetUrl: url })); } }); res.end(); });
客户端监听WebSocket消息
<input type="text" id="videoUrl" placeholder="输入视频URL"> <button id="downloadBtn">下载</button> <script> const ws = new WebSocket(`ws://${window.location.host}`); const urlInput = document.getElementById('videoUrl'); // 监听服务器发送的下载完成消息 ws.onmessage = (event) => { const data = JSON.parse(event.data); if (data.type === 'downloadComplete' && data.targetUrl === urlInput.value) { urlInput.value = ''; } }; // 下载按钮保持原GET请求逻辑即可 document.getElementById('downloadBtn').addEventListener('click', () => { const videoUrl = urlInput.value.trim(); if (!videoUrl) return; window.location.href = `/download?url=${encodeURIComponent(videoUrl)}`; }); </script>
注意事项
- 方案一实现简单,适合大多数单下载场景;方案二适合需要多状态同步的复杂应用。
- 所有URL参数都需要用
encodeURIComponent编码,避免特殊字符导致请求异常。 - 服务器端的错误处理要返回正确的HTTP状态码,确保客户端能捕获并提示用户。
内容的提问来源于stack exchange,提问作者MHH
相关产品推荐
相关产品推荐

