首页 > 解决方案 > 使用ajax处理附件

问题描述

警告: 我正在制作一个 youtube 视频下载器。我仅出于教育目的制作此内容,并不意味着将其用于任何盗版/非法目的。

好的,直奔问题。我有一个运行脚本的 Node.js express 服务器,因此当您向它发送 get 请求时,它要么发送一些包含错误代码和内容的 JSON,要么发送一个 mp3 或 mp4 文件。我没有所有的代码,这是代码:

// Import some libraries
const express = require('express')
const ytdl = require('ytdl-core')
const cp = require('child_process')

var app = express()

app.get('/download', async (req, res) => {
    

     const url = req.query.url
    
    if (url == null) {
        res.header('Access-Control-Allow-Origin','*')
        res.send({err: 'URLNULL', errCode: 1})
        return;
    }
    if (!ytdl.validateURL(url)) {
        res.header('Access-Control-Allow-Origin','*')
        res.send({err: 'INVALIDURL', errCode: 1})        
        return;
    }
    if (req.query.audioonly == 'true') {
        const title = (await ytdl.getBasicInfo(url)).videoDetails.title
    
        const audio = ytdl(url, {
            quality: 'highestaudio'
        }).on('error', (err) => {
           
            if (err.message == 'unable to get local issuer certificate') {
                res.send({err: 'CERTERR', errCode: 1})
                return;

            } else {
                res.send({err: err.message, errCode: 2})
            }
            
        })
        var ffmpegProcess = cp.spawn('ffmpeg', [
            '-hide_banner',
            '-loglevel', 'fatal',
            '-i', 'pipe:3',
            '-f', 'mp3',
            'pipe:1'
        ], {
            stdio: [
                'inherit', 'pipe', 'inherit',
                'pipe',
            ]
            
        })
        audio.pipe(ffmpegProcess.stdio[3])
        res.header( 'Access-Control-Allow-Origin','*');
        res.header('Content-Type', 'audio/mp3')
        res.header('Access-Control-Expose-Headers', 'Content-Disposition')
        res.header('Content-Disposition', `attachment; filename=${title}.mp3`)
        ffmpegProcess.stdout.pipe(res)


    } else {
        const title = (await ytdl.getBasicInfo(url)).videoDetails.title
    const video = ytdl(url, {
        quality: 'highestvideo'
    })
    const audio = ytdl(url, {
        quality: 'highestaudio'
    })
    var ffmpegProcess = cp.spawn('ffmpeg', [
        '-hide_banner',
        '-loglevel', 'fatal',
        '-i', 'pipe:3',
        '-i', 'pipe:4',
        '-map', '0:v',
        '-map', '1:a',
        '-c', 'copy',
        '-movflags', 'frag_keyframe+empty_moov',
        '-f', 'mp4',
        'pipe:1',
    ], {
        stdio: [
            'inherit', 'pipe', 'inherit',
            'pipe', 'pipe',
        ]
    })

    video.pipe(ffmpegProcess.stdio[3])
    audio.pipe(ffmpegProcess.stdio[4])
    res.header( 'Access-Control-Allow-Origin','*');
    res.header('Content-Type', 'video/mp4')
    res.header('Access-Control-Expose-Headers', 'Content-Disposition')
    res.header('Content-Disposition', `attachment; filename=${title}.mp4`);
    
    ffmpegProcess.stdout.pipe(res)
    }
    
})

app.listen(4443)

当我发送一个 GET 请求时,错误的东西工作正常,但是当我收到它时,我似乎找不到下载 mp3/mp4 的正确方法。这是我当前向服务器发送请求的前端 js 函数。

function dlmp3() {
    if (input.value == null) {
        //TODO: Handle error
    }


    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        var binaryData = [];
        binaryData.push(this.response);
        var fileName = this.getResponseHeader("Content-Disposition") //if you have the fileName header available
        console.log(fileName)
        var link=document.createElement('a');
        link.href=window.URL.createObjectURL(new Blob(binaryData, {type: "audio/mp3"}));
        link.download=fileName;
        link.click();
        link.remove()
      }
    };
    xhttp.open("GET", `http://localhost:4443/download?url=${input.value}&audioonly=true`, true);
    xhttp.send();
}

这是一种非常粗略的方法,但它是它做某事的唯一方法(当然,吐出错误除外)。它确实下载了一些东西,但是当我从浏览器转到快速/下载链接时,mp3 比实际大小多 300 kb。此外,它是腐败的。有没有更好的方法来下载附件(我可以使用 Ajax 以外的东西)?

标签: javascriptajaxgetattachment

解决方案


推荐阅读