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

如何用Node.js+Express将网络文件下载保存到服务器本地目录

用Node.js + Express 无交互下载外部文件到服务器指定目录

你要的是服务器端主动下载外部文件并保存到本地目录,res.download()是给前端用户触发下载的,确实不适用这个场景。下面给你两种实用的实现方案:

方案一:用Node.js原生http/https模块(无额外依赖)

不需要装第三方包,直接用Node自带的模块就能实现,还能处理重定向场景:

const express = require('express');
const fs = require('fs');
const http = require('http');
const https = require('https');
const path = require('path');

const app = express();
const PORT = 3000;

// 封装下载函数,返回Promise方便异步调用
function downloadFile(url, savePath) {
  return new Promise((resolve, reject) => {
    // 根据URL协议选择http或https模块
    const client = url.startsWith('https') ? https : http;
    const fileStream = fs.createWriteStream(savePath);

    client.get(url, (response) => {
      // 处理301/302重定向
      if ([301, 302].includes(response.statusCode)) {
        return downloadFile(response.headers.location, savePath)
          .then(resolve)
          .catch(reject);
      }

      // 将响应流写入本地文件
      response.pipe(fileStream);

      fileStream.on('finish', () => {
        fileStream.close();
        resolve(`文件已保存到:${savePath}`);
      });

      fileStream.on('error', (err) => {
        // 下载出错时删除不完整的文件
        fs.unlink(savePath, () => {});
        reject(err);
      });
    }).on('error', (err) => {
      reject(err);
    });
  });
}

// 示例路由:访问这个接口就会触发下载
app.get('/save-external-file', async (req, res) => {
  const externalUrl = 'http://www.example.com/uploads/file.xyz';
  // 指定服务器上的保存目录(这里是项目根目录下的downloads文件夹)
  const saveDir = path.join(__dirname, 'downloads');
  const savePath = path.join(saveDir, 'file.xyz');

  // 先确保保存目录存在,不存在就创建
  if (!fs.existsSync(saveDir)) {
    fs.mkdirSync(saveDir, { recursive: true });
  }

  try {
    const result = await downloadFile(externalUrl, savePath);
    res.status(200).send(result);
  } catch (err) {
    res.status(500).send(`下载失败:${err.message}`);
  }
});

app.listen(PORT, () => {
  console.log(`服务器运行在 http://localhost:${PORT}`);
});

方案二:用axios(代码更简洁,自动处理重定向)

如果觉得原生模块写起来麻烦,可以用axios库,它会自动处理重定向,代码更清爽:

首先安装axios:

npm install axios

然后写代码:

const express = require('express');
const fs = require('fs');
const axios = require('axios');
const path = require('path');

const app = express();
const PORT = 3000;

app.get('/save-external-file', async (req, res) => {
  const externalUrl = 'http://www.example.com/uploads/file.xyz';
  const saveDir = path.join(__dirname, 'downloads');
  const savePath = path.join(saveDir, 'file.xyz');

  // 确保保存目录存在
  if (!fs.existsSync(saveDir)) {
    fs.mkdirSync(saveDir, { recursive: true });
  }

  try {
    // 以流的方式请求文件,避免大文件占用过多内存
    const response = await axios({
      url: externalUrl,
      method: 'GET',
      responseType: 'stream'
    });

    const fileStream = fs.createWriteStream(savePath);
    response.data.pipe(fileStream);

    // 等待文件写入完成
    await new Promise((resolve, reject) => {
      fileStream.on('finish', resolve);
      fileStream.on('error', reject);
    });

    res.status(200).send(`文件已保存到:${savePath}`);
  } catch (err) {
    res.status(500).send(`下载失败:${err.message}`);
  }
});

app.listen(PORT, () => {
  console.log(`服务器运行在 http://localhost:${PORT}`);
});

注意事项

  • 要保证服务器对目标保存目录有读写权限,否则会保存失败
  • 如果外部文件需要身份验证(比如带Cookie、Token),需要在请求里加对应的请求头。比如axios里可以加headers: { Cookie: 'your-cookie', Authorization: 'Bearer your-token' }
  • 大文件建议用流的方式处理(两个方案都是流处理),避免内存溢出
  • 可以根据需求添加超时设置,比如axios里加timeout: 30000(30秒超时)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:23:16