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

Express-Zip集成Node.js批量下载Instagram媒体失败求助

解决express-zip与Instagram媒体多文件打包下载问题

问题根源分析

  1. 全局变量污染:arrayDocs是全局变量,多次请求会导致旧的文件列表被重复添加,最终压缩包内容混乱。
  2. express-zip不支持远程URL:express-zip的path参数仅支持本地文件路径,直接传入Instagram的远程URL无法读取内容,导致生成空压缩包(66字节)。
  3. 异步逻辑处理不当:循环中直接调用res.zip,但未等待所有远程文件下载完成,服务器可能提前响应或卡住。

修正后的代码

const express = require("express");
const request = require("request").defaults({ encoding: null }); // 配置默认返回Buffer
const bodyParser = require("body-parser");
const instaAPI = require("igdown-scrapper");
const app = express();
const port = 3000;
const zip = require("express-zip");

app.use(bodyParser.urlencoded({ extended: false }));
app.set("view engine", "ejs");

app.get("/", (req, res) => {
  res.render("index");
});

app.post("/download", async (req, res) => {
  const url = req.body.url;
  if (!url || !url.startsWith("https://www.instagram.com/")) {
    return res.render("index", { error: "Invalid URL" });
  }

  try {
    const data = await instaAPI(url);
    // 处理多文件情况
    if (Array.isArray(data) && data.length > 1) {
      const zipFiles = [];
      // 并行下载所有媒体文件
      await Promise.all(data.map(async (item, index) => {
        const mediaUrl = item.url[0].url;
        const ext = item.url[0].ext;
        const fileName = `${Date.now()}-${index}.${ext}`;
        
        // 下载远程文件到Buffer
        const fileBuffer = await new Promise((resolve, reject) => {
          request.get(mediaUrl, (err, response, body) => {
            if (err || response.statusCode !== 200) {
              return reject(new Error(`Failed to download ${mediaUrl}`));
            }
            resolve(body);
          });
        });
        
        // 添加到压缩包列表(使用data参数传递Buffer)
        zipFiles.push({
          data: fileBuffer,
          name: fileName
        });
      }));

      // 生成并发送压缩包
      res.zip(zipFiles);
    } else {
      // 单文件下载逻辑
      const mediaUrl = data.url[0].url;
      const ext = data.url[0].ext;
      const fileName = `${Date.now()}.${ext}`;
      
      request.get(mediaUrl, (err, response, body) => {
        if (err || response.statusCode !== 200) {
          return res.status(400).send("Error downloading media");
        }
        res.setHeader("Content-Type", "application/octet-stream");
        res.setHeader("Content-Disposition", `attachment; filename="${fileName}"`);
        res.send(body);
      });
    }
  } catch (err) {
    console.error(err);
    res.render("index", { error: "Failed to fetch Instagram media" });
  }
});

app.listen(port, () => {
  console.log("App is listening on port 3000");
});

关键改进点

  • 局部变量替代全局变量:将arrayDocs改为请求内的zipFiles,避免跨请求数据污染。
  • 支持远程文件压缩:通过request下载远程文件到Buffer,使用express-zip的data参数传递文件内容,而非无效的远程URL。
  • 异步并行处理:用Promise.all并行下载所有媒体文件,确保所有文件准备完成后再生成压缩包,避免服务器卡住或提前响应。
  • 错误捕获:添加try/catch捕获API请求和文件下载中的错误,提升稳定性。

内容的提问来源于stack exchange,提问作者tionxs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 20:12:46