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

咨询:基于Node.js实现远程服务器文件变更检测与下载方案

检测远程文件变更并下载的Node.js实现方案

关于fs模块的说明

fs模块仅负责本地文件系统的读写操作,无法直接访问远程服务器上的文件,所以单独用fs模块满足不了需求,需要结合HTTP/HTTPS请求模块来实现。

核心实现思路

通过与远程服务器交互获取文件的标识信息(如修改时间、哈希值),对比本地记录的标识,判断文件是否变更,若变更则下载覆盖本地文件。

方案1:利用HTTP响应头(ETag/Last-Modified)

这是最常用的轻量方案,依赖服务器返回的标准HTTP头:

  • 首次请求时,记录返回的ETag(文件哈希标识)或Last-Modified(最后修改时间)
  • 后续请求时,在请求头中携带If-None-Match(对应ETag)或If-Modified-Since(对应Last-Modified)
  • 服务器返回304状态码则说明文件未变更,返回200则说明文件已更新,此时下载文件

示例代码:

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

const remoteFileUrl = 'https://example.com/your-target-file.txt';
const localFilePath = path.join(__dirname, 'local-copy.txt');
const recordPath = path.join(__dirname, 'file-record.json');

// 读取本地记录的文件标识
function getLocalRecord() {
  try {
    return JSON.parse(fs.readFileSync(recordPath, 'utf8'));
  } catch (err) {
    return {};
  }
}

// 保存新的文件标识到本地
function saveLocalRecord(record) {
  fs.writeFileSync(recordPath, JSON.stringify(record, null, 2));
}

// 检查并下载文件
function checkAndDownload() {
  const localRecord = getLocalRecord();
  const requestOptions = {
    headers: {}
  };

  // 携带已记录的ETag或Last-Modified
  if (localRecord.etag) {
    requestOptions.headers['If-None-Match'] = localRecord.etag;
  } else if (localRecord.lastModified) {
    requestOptions.headers['If-Modified-Since'] = localRecord.lastModified;
  }

  https.get(remoteFileUrl, requestOptions, (res) => {
    if (res.statusCode === 304) {
      console.log('文件未变更,无需下载');
      return;
    }

    if (res.statusCode === 200) {
      // 记录新的标识
      const newRecord = {
        etag: res.headers.etag,
        lastModified: res.headers['last-modified']
      };
      saveLocalRecord(newRecord);

      // 下载文件到本地
      const fileStream = fs.createWriteStream(localFilePath);
      res.pipe(fileStream);
      fileStream.on('finish', () => {
        console.log('文件已更新并下载完成');
      });
    } else {
      console.log(`请求失败,状态码:${res.statusCode}`);
    }
  }).on('error', (err) => {
    console.error('请求出错:', err);
  });
}

// 可以设置定时检测,比如每30分钟执行一次
setInterval(checkAndDownload, 30 * 60 * 1000);
// 首次执行检测
checkAndDownload();

方案2:对比文件哈希值

如果服务器不支持ETag/Last-Modified,可以下载文件的哈希值文件(比如单独的file-hash.txt),对比本地计算的哈希值:

  • 先请求远程的哈希文件,获取最新哈希
  • 计算本地文件的哈希值(用crypto模块)
  • 若两者不一致,则下载完整文件并更新本地哈希记录

示例代码片段(核心部分):

const crypto = require('crypto');

// 计算本地文件的SHA256哈希
function getLocalFileHash(filePath) {
  try {
    const fileBuffer = fs.readFileSync(filePath);
    return crypto.createHash('sha256').update(fileBuffer).digest('hex');
  } catch (err) {
    return null;
  }
}

// 检查哈希并下载
async function checkHashAndDownload() {
  // 先获取远程哈希
  const hashRes = await new Promise((resolve, reject) => {
    https.get('https://example.com/file-hash.txt', (res) => {
      let data = '';
      res.on('data', (chunk) => data += chunk);
      res.on('end', () => resolve(data.trim()));
      res.on('error', reject);
    });
  });

  const localHash = getLocalFileHash(localFilePath);
  if (!localHash || localHash !== hashRes) {
    // 下载文件逻辑同方案1
    console.log('文件哈希变更,开始下载');
    // ...下载代码
    // 下载完成后更新本地哈希记录
    fs.writeFileSync(path.join(__dirname, 'local-hash.txt'), hashRes);
  } else {
    console.log('文件未变更');
  }
}

注意事项

  • 确保远程服务器允许HEAD请求(如果只想获取头信息而不下载文件,用HEAD请求更高效)
  • 处理网络异常、文件读写权限问题
  • 定时检测的间隔根据实际需求调整,避免过于频繁请求给服务器造成压力

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 14:03:39