You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 18:43:23