目录

node 原生模块下载失败问题

使用 http 模块下载 https 的链接会报异常

这时候需要使用 https 模块下载,下面是兼容 http 和 https 的下载函数:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
const fs = require("fs");
const path = require("path");
const http = require("http");
const https = require("https");

async function download(url, filePath) {
  const proto = url.startsWith("https") ? https : http;

  return new Promise((resolve, reject) => {
    const file = fs.createWriteStream(filePath);
    let fileInfo = null;

    // const request = proto.get(url, response => {
    const request = proto.get(url, (response) => {
      if (response.statusCode !== 200) {
        fs.unlink(filePath, () => {
          reject(new Error(`Failed to get '${url}' (${response.statusCode})`));
        });
        return;
      }

      fileInfo = {
        mime: response.headers["content-type"],
        size: parseInt(response.headers["content-length"], 10),
      };

      response.pipe(file);
    });

    // The destination stream is ended by the time it's called
    file.on("finish", () => resolve(fileInfo));

    request.on("error", (err) => {
      fs.unlink(filePath, () => reject(err));
    });

    file.on("error", (err) => {
      fs.unlink(filePath, () => reject(err));
    });

    request.end();
  });
}

const url = "https://100.100.22.140/files/1.0.zip";

download(url, path.resolve("./download"));

目标下载地址是自签的 https 证书,下载会报异常

但是如果目标下载地址是自签的 https 证书,则下载也会失败,这时候有两种解决方式:

第一种:环境变量设置 NODE_TLS_REJECT_UNAUTHORIZED

1
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;

第二种:https 模块下载时加上 { rejectUnauthorized: false } 可选项

具体的例子如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
const fs = require("fs");
const path = require("path");
const http = require("http");
const https = require("https");

// process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;

async function download(url, filePath) {
  const proto = url.startsWith("https") ? https : http;

  return new Promise((resolve, reject) => {
    const file = fs.createWriteStream(filePath);
    let fileInfo = null;

    // const request = proto.get(url, response => {
    const request = proto.get(
      url,
      { rejectUnauthorized: false },
      (response) => {
        if (response.statusCode !== 200) {
          fs.unlink(filePath, () => {
            reject(
              new Error(`Failed to get '${url}' (${response.statusCode})`)
            );
          });
          return;
        }

        fileInfo = {
          mime: response.headers["content-type"],
          size: parseInt(response.headers["content-length"], 10),
        };

        response.pipe(file);
      }
    );

    // The destination stream is ended by the time it's called
    file.on("finish", () => resolve(fileInfo));

    request.on("error", (err) => {
      fs.unlink(filePath, () => reject(err));
    });

    file.on("error", (err) => {
      fs.unlink(filePath, () => reject(err));
    });

    request.end();
  });
}

const url = "https://100.100.22.140/files/1.0.zip";

download(url, path.resolve("./download"));

参考链接