# 网络文件下载

# 获取网络文件名

使用path模块获取网络文件名。

const fileName = fileName ? fileName : Path.basename(fileUrl);

# 创建网络连接

由于httphttps所使用的获取下载流模块不同,所以需要对不同协议创建不同的连接。

const url = URL.parse(fileUrl);
let req = null;
if (url.protocol === 'http:') req = http.request(url);
if (url.protocol === 'https:') req = https.request(url);

# 创建文件写入流

由于http/https获取的文件信息是流信息,所以需要使用fs模块来创建文件写入流

const stream = fs.createWriteStream(path + fileName);

# 监听网络连接并写入文件

监听连接的响应,获取返回信息流并写入文件。因为io流非常耗费性能,所以每写完一个文件必须要将其关闭,释放资源。

req.on('response', (res) => {
  const len = parseInt(res.headers['content-length'], 10);

  const bar = new ProgressBar(`downloading ${fileName} [:bar] :rate/bps size: ${len}KB :percent :etas`, {
    complete: '=',
    incomplete: '-',
    width: 100,
    total: len,
  })

  res.on('data', chunk => {
    bar.tick(chunk);
    stream.write(chunk, 'utf-8');
  })

  res.on('end', _ => {
    console.log('/n')
    stream.end();
  })

  res.on('error', err => {
    console.error(err);
  })
})
req.end();

# 完整代码

'use strict';

const ProgressBar = require('progress');
const https = require('https');
const http = require('http');
const fs = require('fs');
const Path = require('path');
const URL = require('url');

/**
 * 下载单个文件
 * @param {String} fileUrl 网络文件路径
 * @param {String} path 文件存放位置
 * @param {String} fileName 文件名
 */
const downloadFile = (fileUrl, path, fileName) => {
  fileName = fileName ? fileName : Path.basename(fileUrl);
  path = path ? path : './';
  const stream = fs.createWriteStream(path + fileName);

  const url = URL.parse(fileUrl);
  let req = null;
  if (url.protocol === 'http:') req = http.request(url);
  if (url.protocol === 'https:') req = https.request(url);

  req.on('response', (res) => {
    const len = parseInt(res.headers['content-length'], 10);

    const bar = new ProgressBar(`downloading ${fileName} [:bar] :rate/bps size: ${len}KB :percent :etas`, {
      complete: '=',
      incomplete: '-',
      width: 100,
      total: len,
    })
  
    res.on('data', chunk => {
      bar.tick(chunk);
      stream.write(chunk, 'utf-8');
    })
  
    res.on('end', _ => {
      console.log('/n')
      stream.end();
    })

    res.on('error', err => {
      console.error(err);
    })
  })
  req.end();
}

/**
 * 下载多个文件
 * @param {String[]} fileUrls 网络文件路径数组
 * @param {String} path 文件存放位置
 */
const downloadFiles = (fileUrls, path) => {
  if (fileUrls && fileUrls.length === 0) throw new Error('fileUrls cannot be empty');
  path = path ? path : './';

  fileUrls.forEach(url => {
    downloadFile(url, path)
  })
}

module.exports = {
  downloadFile,
  downloadFiles,
}
上次更新时间: 11/7/2021, 2:23:15 PM

添加微信

获取阿里云更多优惠

阿里云最新活动