【小沐学前端】Node.js实现Web服务器(http模块)

🍺Web服务器系列相关文章编写如下🍺:

  1. 🎈【Web开发】Node.js实现Web服务器(http模块)🎈
  2. 🎈【Web开发】Node.js实现Web服务器(express模块)🎈
  3. 🎈【Web开发】Python实现Web服务器(Flask入门)🎈
  4. 🎈【Web开发】Python实现Web服务器(Flask测试)🎈
  5. 🎈【Web开发】Python实现Web服务器(Tornado入门)🎈
  6. 🎈【Web开发】Python实现Web服务器(Tornado+flask+nginx)🎈
  7. 🎈【Web开发】Python实现Web服务器(FastAPI)🎈
  8. 🎈【Web开发】Android手机上基于Termux实现Web服务器(Python、node.js)🎈

Node.js 是一个免费的、开源的、跨平台的 JavaScript 运行时环境,允许开发人员在浏览器之外编写命令行工具和服务器端脚本。

在这里插入图片描述

1、简介

官网地址:https://nodejs.org/

Node.js 是一个开源和跨平台的 JavaScript 运行时环境。它是几乎任何类型的项目的流行工具!

Node.js 在浏览器之外运行 Google Chrome 的核心 V8 JavaScript 引擎。这使得 Node.js 非常高效。

Node.js 应用程序在单个进程中运行,无需为每个请求创建新线程。Node.js 在其标准库中提供了一组异步 I/O 原语,可防止 JavaScript 代码阻塞,通常,Node.js 中的库是使用非阻塞范例编写的,使阻塞行为成为例外而不是常态。

当 Node.js 执行 I/O 操作时,例如从网络读取、访问数据库或文件系统,而不是阻塞线程并浪费 CPU 周期等待,Node.js 将在响应返回时恢复操作。

这允许 Node.js 处理与单个服务器的数千个并发连接,而​​不会引入管理线程并发的负担,这可能是错误的重要来源。

Node.js 有一个独特的优势,因为数百万为浏览器编写 JavaScript 的前端开发人员现在能够编写除了客户端代码之外的服务器端代码,而无需学习完全不同的语言。

在 Node.js 中,可以毫无问题地使用新的 ECMAScript 标准,因为您不必等待所有用户更新他们的浏览器 - 您可以通过更改 Node.js 版本来决定使用哪个 ECMAScript 版本,您还可以通过运行带有标志的 Node.js 来启用特定的实验功能。
在这里插入图片描述

2、下载和安装

https://nodejs.org/en/download/
https://unofficial-builds.nodejs.org/download/release/

在这里插入图片描述
在这里插入图片描述

当前官网最新版本:
Latest LTS Version: 16.14.2 (includes npm 8.5.0)

查看node版本:

node -v

在这里插入图片描述

查看npm版本:

npm -v

在这里插入图片描述

3、NPM使用

npm 是 Node.js 标准的软件包管理器。
它起初是作为下载和管理 Node.js 包依赖的方式,但其现在也已成为前端 JavaScript 中使用的工具。
Yarn 是 npm 的一个替代选择。

3.1 下载

npm 可以管理项目依赖的下载。

  • 安装所有依赖
    如果项目具有 package.json 文件,则通过运行:
npm install

它会在 node_modules 文件夹(如果尚不存在则会创建)中安装项目所需的所有东西。

  • 安装单个软件包
npm install <package-name>

通常会在此命令中看到更多标志:
–save 安装并添加条目到 package.json 文件的 dependencies。
–save-dev 安装并添加条目到 package.json 文件的 devDependencies。
区别主要是,devDependencies 通常是开发的工具(例如测试的库),而 dependencies 则是与生产环境中的应用程序相关。

  • 更新软件包

检查所有软件包是否有满足版本限制的更新版本。

npm update

也可以指定单个软件包进行更新:

npm update <package-name>

3.2 版本控制

除了简单的下载外,npm 还可以管理版本控制,因此可以指定软件包的任何特定版本,或者要求版本高于或低于所需版本。很多时候,一个库仅与另一个库的主版本兼容。

3.3 运行任务

package.json 文件支持一种用于指定命令行任务(可通过使用以下方式运行)的格式:

npm run <task-name>

比如package.json可以写成如下内容:

{
  "scripts": {
    "start-dev": "node lib/server-development",
    "start": "node lib/server-production"
  },
}

{
  "scripts": {
    "watch": "webpack --watch --progress --colors --config webpack.conf.js",
    "dev": "webpack --progress --colors --config webpack.conf.js",
    "prod": "NODE_ENV=production webpack -p --config webpack.conf.js",
  },
}

因此可以运行如下,而不是输入那些容易忘记或输入错误的长命令:

$ npm run watch
$ npm run dev
$ npm run prod

3.4 软件包安装位置

当使用 npm 安装软件包时,可以执行两种安装类型:

  • 本地安装
  • 全局安装

默认情况下,当输入 npm install 命令时,例如:

npm install vue

软件包会被安装到当前文件树中的 node_modules 子文件夹下。
在这种情况下,npm 还会在当前文件夹中存在的 package.json 文件的 dependencies 属性中添加 vue条目。
使用 -g 标志可以执行全局安装:

npm install -g vue

在这种情况下,npm 不会将软件包安装到本地文件夹下,而是使用全局的位置。
npm root -g 命令会告知其在计算机上的确切位置。
当添加了 -D 或 --save-dev 标志时,则会将其安装为开发依赖项(会被添加到 devDependencies 列表)。

npm root -g

在这里插入图片描述
也可以通过如下代码查看全局安装路径:

npm config get prefix

在这里插入图片描述

3.5 查看 npm 包安装的版本

若要查看所有已安装的 npm 软件包(包括它们的依赖包)的最新版本,则:

npm list

也可以打开 package-lock.json 文件,但这需要进行一些视觉扫描。
npm list -g 也一样,但适用于全局安装的软件包。

npm list -g
npm list -g --depth 0

在这里插入图片描述
如果要查看软件包在 npm 仓库上最新的可用版本,则运行 npm view [package_name] version:

npm view vue version

在这里插入图片描述

3.6 安装 npm 包的旧版本

可以使用 @ 语法来安装 npm 软件包的旧版本:

npm install <package>@<version>
npm install cowsay
npm install cowsay@1.2.0
npm install -g webpack@4.16.4

可能还有需要列出软件包所有的以前的版本。 可以使用 npm view versions:
在这里插入图片描述

3.7 卸载 npm 软件包

若要卸载之前在本地安装(在 node_modules 文件夹使用 npm install )的软件包,则从项目的根文件夹(包含 node_modules 文件夹的文件夹)中运行:

npm uninstall <package-name>

如果使用 -S 或 --save 标志,则此操作还会移除 package.json 文件中的引用。
如果程序包是开发依赖项(列出在 package.json 文件的 devDependencies 中),则必须使用 -D 或 --save-dev 标志从文件中移除:

npm uninstall -S <package-name>
npm uninstall -D <package-name>

如果该软件包是全局安装的,则需要添加 -g 或 --global 标志:

npm uninstall -g <package-name>
npm uninstall -g vue

3.8 npm 淘宝镜像的安装

由于node下载第三方依赖包是从国外服务器下载,但是下载的速度是非常的缓慢且有可能会出现异常。所以为了提高效率,我们还是把npm的镜像源替换成淘宝的镜像源。

只在当前工程中使用阿里定制的cnpm命令行工具,代码如下:

$ npm install cnpm --registry=https://registry.npm.taobao.org

在这里插入图片描述

使用阿里定制的cnpm命令行工具代替全局默认的npm,输入以下代码

$ npm install -g cnpm --registry=https://registry.npm.taobao.org

在这里插入图片描述

检测是否安装成功:

$ cnpm -v

在这里插入图片描述

安装成功之后,以后安装依赖包的方式和npm的是一样的,只是npm的命令换成是cnpm就可以了。

假如你已经习惯了使用npm的安装方式的,不想去下载阿里的cnpm命令工具的话,很简单,我们直接将node的仓库地址换成淘宝仓库地址。

# 单次使用
$ npm install --registry=https://registry.npm.taobao.org

# 永久使用
## 直接命令行的设置
$ npm config set registry https://registry.npm.taobao.org
## 手动修改设置
1.打开.npmrc文件(C:\Program Files\nodejs\node_modules\npm\npmrc,没有的话可以使用git命令行建一个( touch .npmrc),用cmd命令建会报错)
2.增加 registry =https://registry.npm.taobao.org  即可。

## 配置后可通过下面方式来验证是否成功
$ npm config get registry

## 如果想还原npm仓库地址的话
$ npm config set registry https://registry.npmjs.org/

在这里插入图片描述

4、主要模块module

4.1 process

如何从 Node.js 读取环境变量:

console.log(process.env)

在这里插入图片描述

4.2 readline

  • readline

从版本 7 开始,Node.js 提供了 readline 模块来执行以下操作:每次一行地从可读流(例如 process.stdin 流,在 Node.js 程序执行期间该流就是终端输入)获取输入。
在 Node.js 中从命令行接收输入:

  • Inquirer

Inquirer.js 软件包则提供了更完整、更抽象的解决方案。

const inquirer = require('inquirer')

var questions = [
  {
    type: 'input',
    name: 'name',
    message: "你叫什么名字?"
  }
]

inquirer.prompt(questions).then(answers => {
  console.log(`你好 ${answers['name']}!`)
})

在这里插入图片描述

4.3 fs

  • open
    文件描述符是使用 fs 模块提供的 open() 方法打开文件后返回的:
const fs = require('fs')

fs.open(__dirname + '/ReadMe.txt', 'r', (err, fd) => {
  //fd 是文件描述符。
  console.log("open: " + fd);
})

在这里插入图片描述

  • stat
    每个文件都带有一组详细信息,可以使用 Node.js 进行检查。
const fs = require('fs')

fs.stat(__dirname + '/ReadMe.txt', (err, stats) => {
  if (err) {
    console.error(err)
    return
  }
  //可以访问 `stats` 中的文件属性
  console.log("ctime: " + stats.ctime);
  console.log("atime: " + stats.atime);
  console.log("mtime: " + stats.mtime);
  console.log("size: " + stats.size);
})

在这里插入图片描述

  • readFile
    在 Node.js 中读取文件最简单的方式是使用 fs.readFile() 方法,向其传入文件路径、编码、以及会带上文件数据(以及错误)进行调用的回调函数:
const fs = require('fs')

fs.readFile(__dirname + '/ReadMe.txt', 'utf8' , (err, data) => {
  if (err) {
    console.error(err)
    return
  }
  console.log(data)
})

在这里插入图片描述

  • writeFile
    在 Node.js 中写入文件最简单的方式是使用 fs.writeFile() API。
const fs = require('fs')

const content = '一些内容'
fs.writeFile(__dirname + '/test.txt', content, err => {
  if (err) {
    console.error(err)
    return
  }
  //文件写入成功。
})

在这里插入图片描述

4.4 path

path 模块提供了许多非常实用的函数来访问文件系统并与文件系统进行交互。

const path = require('path')
path.basename('/test/something') //something
path.basename('/test/something.txt') //something.txt
path.basename('/test/something.txt', '.txt') //something

path.dirname('/test/something') // /test
path.dirname('/test/something/file.txt') // /test/something

path.extname('/test/something') // ''
path.extname('/test/something/file.txt') // '.txt'

path.isAbsolute('/test/something') // true
path.isAbsolute('./test/something') // false

const name = 'joe'
path.join('/', 'users', name, 'notes.txt') //'/users/joe/notes.txt'

path.normalize('/users/joe/..//test.txt') //'/users/test.txt'

path.parse('/users/test.txt')
// {
//     root: '/',
//     dir: '/users',
//     base: 'test.txt',
//     ext: '.txt',
//     name: 'test'
//   }

path.relative('/Users/joe', '/Users/joe/test.txt') //'test.txt'
path.relative('/Users/joe', '/Users/joe/something/test.txt') //'something/test.txt'

path.resolve('joe.txt') //'/Users/joe/joe.txt' 如果从主文件夹运行
path.resolve('tmp', 'joe.txt') //'/Users/joe/tmp/joe.txt' 如果从主文件夹运行
path.resolve('/etc', 'joe.txt') //'/etc/joe.txt'

4.5 os

Node.js 操作系统模块,该模块提供了许多函数,可用于从底层的操作系统和程序运行所在的计算机上检索信息并与其进行交互。

os.arch()
os.cpus()
os.endianness()
os.freemem()
os.homedir()
os.hostname()
os.loadavg()
os.networkInterfaces()
os.platform()
os.release()
os.tmpdir()
os.totalmem()
os.type()
os.uptime()
os.userInfo()

比如其中返回关于系统上可用的 CPU 的信息,代码如下:

const os = require('os')
console.log(os.cpus())

在这里插入图片描述

4.6 http

HTTP 核心模块是 Node.js 网络的关键模块。
HTTP 模块提供了 5 个类:

  1. http.Agent
  2. http.ClientRequest
  3. http.Server
  4. http.ServerResponse
  5. http.IncomingMessage
// http://nodejs.cn/learn/the-nodejs-http-module
const http = require('http')
console.log(http.METHODS);
console.log(http.STATUS_CODES);

在这里插入图片描述

5、基于http模块的Web功能

4.1 最简单示例

  • server1.js:
var http = require("http");

http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}).listen(3000);

运行结果如下:
在这里插入图片描述

4.2 处理字符串

https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/

  • server2.js:
const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

运行结果如下:
在这里插入图片描述

4.3 处理网页文件

在网页上对所有文件进行文本方式的显示,代码如下所示。

  • server3.js:
var http = require('http');
var fs = require('fs'); 

var documentRoot = __dirname;
console.log("Workdir: " + __dirname);

var server = http.createServer(function (req, res) {
    var file = documentRoot + req.url;
    console.log("Request: " + file);
    
    fs.readFile(file, function (err, data) {
        if (err) {
            res.writeHeader(404, {
                'content-type': 'text/html;charset="utf-8"'
            });
            res.write('<h1>404错误</h1><p>你要找的页面不存在</p>');
            res.end();
        } else {
            res.writeHeader(200, {
                'content-type': 'text/html;charset="utf-8"'
            });
            res.write(data); 
            res.end();
        }

    });
}).listen(3000);

console.log('Server running at http://127.0.0.1:3000/');

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.4 处理图片文件

在上面的基础上,增加对图片文件的显示,代码如下所示。

  • server3_2.js:
var http = require('http');
var fs = require('fs');
var url = require('url');
const path = require('path');

// 创建服务器
http.createServer(function (req, res) {
    // 解析请求,包括文件名
    var pathname = url.parse(req.url).pathname;
   //获取node.exe的绝对路径
   console.log(process.execPath);//D:\nodejs\node.exe

    //当前文件(即server.js)的绝对路径
    console.log(__filename);//D:\nodeTest\node_path\lib\server.js

   //存放当前文件(即server.js)文件夹的绝对路径
   console.log(__dirname);//D:\nodeTest\node_path\lib

   //从所传入的文件路径(相对或绝对)中获取存放传入文件的文件夹的相对或绝对路径 
   //(例如 传入 public/home.html 则返回的是public)
   console.log(path.dirname(__filename));//D:\nodeTest\node_path\lib

   //执行当前脚本(即server.js)的位置 (例如 在根目录下执行 node ./xxx/xxx/a.js 则返回的是根目录地址 )
   console.log(process.cwd());//D:\nodeTest\node_path\lib

   //'a/b/c'和'../src' 组合而成的绝对路径 文件或文件夹都行
    //例如 console.log(path.resolve('a/b/c', '../src'));//D:\nodeTest\node_path\lib\a\b\src
    console.log(path.resolve(__dirname, '../public'));//D:\nodeTest\node_path\public

    //'a/b/c'和'../src'组成的相对路径
    //console.log(path.join('a/b/c', '../src'));//a\b\src
    console.log(path.join(__dirname, '../public'));//D:\nodeTest\node_path\public

    // 输出请求的文件名
    console.log("Request for " + pathname + " received.");
    if (pathname == "/") {
        fs.stat('/index.html', function (err, stat) {
            if (stat && stat.isFile()) {
                console.log('index.html existed.');
            } else {
                console.log('index.html not existed.');
            }
        });

        fs.readFile("index.html", function (err, data) {
            if (err) {
                res.statusCode = 200;
                res.setHeader('Content-Type', 'text/plain');
                res.end('Hello World');
            } else {
                res.writeHead(200, {
                    "Content-Type": "text/html;charset=UTF-8"
                });
                res.end(data);
            }
        });
    } else if (pathname.indexOf(".jpg") != -1) {
        
        fs.readFile(__dirname + pathname, 'binary', function (err, data) {
            if (err) {
                console.log(err);
            } else {
                res.writeHead(200, {'Content-type':'image/jpeg'});
                res.write(data, 'binary');
                res.end();
            }
        });
    } else {
        // 从文件系统中读取请求的文件内容
        fs.readFile(__dirname + pathname, function (err, data) {
            if (err) {
                console.log(err);
                // HTTP 状态码: 404 : NOT FOUND
                // Content Type: text/html
                res.writeHead(404, {
                    'Content-Type': 'text/html'
                });
            } else {
                // HTTP 状态码: 200 : OK
                // Content Type: text/html
                res.writeHead(200, {
                    'Content-Type': 'text/html;charset=utf-8'
                });

                // 响应文件内容
                res.write(data.toString());
            }
            //  发送响应数据
            res.end();
        });
    }

}).listen(3000);

// 控制台会输出以下信息
console.log('Server running at http://127.0.0.1:3000/');
  • web服务器运行:
    在这里插入图片描述

  • 浏览器客户端访问:
    在这里插入图片描述

  1. 输出字符串
    在这里插入图片描述
  2. 输出文本文件
    在这里插入图片描述
  3. 输出图片文件:
    在这里插入图片描述
  4. 输出网页文件:
    在这里插入图片描述
  • 另外一个例子:
var fs = require('fs');

var read = {
    //读取自定义文件
    read_raw: function (file_path, func) {
        fs.readFile(file_path, function (err, data) {
            if (err) {
                console.log(err);
            } else {
                func(data.toString());
            }
        })
    },
    //读取文本文件
    read_raw: function (file_path, res) {
        fs.readFile(file_path, function (err, data) {
            if (err) {
                console.log(err);
            } else {
                res.write(data);
                res.end();
            }
        })
    },
    //读取二进制文件
    //res.writeHead(200, {'Content-type':'image/jpeg'});
    //res.writeHead(200, {'Content-type':'text/html; charset=utf-8'});
    read_binary: function (file_path, res) {
        fs.readFile(file_path, 'binary', function (err, data) {
            if (err) {
                console.log(err);
            } else {
                res.write(data, 'binary');
                res.end();
            }
        })
    }
}

module.exports = read;

//var file_read = require('./read_files');
//file_read.read_img('./views/1.png',res);
//file_read.read_file('./views/login.html', call)

4.5 处理文件流pipe

  • 从磁盘直接读取文件:
const http = require('http')
const fs = require('fs')

const server = http.createServer(function(req, res) {
  fs.readFile(__dirname + '/VSMsiLog0284.txt', (err, data) => {
    res.end(data)
  })
})
server.listen(3000)
  • 使用流读取文件:
const http = require('http')
const fs = require('fs')

const server = http.createServer((req, res) => {
  const stream = fs.createReadStream(__dirname + '/VSMsiLog0284.txt')
  stream.pipe(res)
})
server.listen(3000)

在这里插入图片描述

4.6 处理pdf文件

npm install pdf-lib

在这里插入图片描述

const { PDFDocument, StandardFonts, rgb } = require('pdf-lib');
const fs = require('fs');

run().catch(err => console.log(err));

async function run() {
    // Create a new document and add a new page
    const doc = await PDFDocument.create();
    const page = doc.addPage();

    // Load the image and store it as a Node.js buffer in memory
    let img = fs.readFileSync('./contributors_1.png');
    img = await doc.embedPng(img);

    // Draw the image on the center of the page
    const {
        width,
        height
    } = img.scale(0.1);
    page.drawImage(img, {
        x: 10,
        y: page.getHeight() - height - 10,
        width,
        height
    });

    // Draw the text on the top of the page
    const helveticaFont = await doc.embedFont(StandardFonts.Helvetica);
    page.setFont(helveticaFont)

    page.moveTo(5, 200)
    page.drawText('The Life of an Egg', {
        size: 36
    })

    page.moveDown(36)
    page.drawText('An Epic Tale of Woe', {
        size: 30
    })

    page.drawText(
        `Humpty Dumpty sat on a wall \n` +
        `Humpty Dumpty had a great fall; \n` +
        `All the king's horses and all the king's men \n` +
        `Couldn't put Humpty together again. \n`, {
            x: 25,
            y: 100,
            font: helveticaFont,
            size: 24,
            color: rgb(1, 0, 0),
            lineHeight: 24,
            opacity: 0.75,
        },
    );

    // Write the PDF to a file
    fs.writeFileSync('./test.pdf', await doc.save());
}

在这里插入图片描述

4.7 处理zip压缩文件

npm install archiver
  • 压缩文件和文件夹:
var fs = require('fs');
var archiver = require('archiver');

var output = fs.createWriteStream('archiver-unzip.zip');
var archive = archiver('zip');

output.on('close', function () {
    console.log(`总共 ${archive.pointer()} 字节`)
    console.log('fs close.')
});
output.on('end', function () {
    console.log('fs end.')
});

archive.on('error', function (err) {
    throw err;
});

archive.on('warning', function (err) {
    if (err.code === 'ENOENT') {
        console.warn('archive warning.')
    } else {
        throw err
    }
})

archive.pipe(output);

// archive.bulk([{
//     src: ['a/**']
// }]);

// 从子目录追加文件并将其命名为“新子dir”在存档中
archive.directory('node_modules/', 'node_modules')

// 从流中追加文件
let file1 = __dirname + '/eula.1031.txt'
archive.append(fs.createReadStream(file1), {
    name: 'eula.1031.txt'
})

// 从字符串追加文件
archive.append('To see a world in a grain of sand.', {
    name: 'file2.txt'
})

// 从缓冲区追加文件
let buffer3 = Buffer.from('And a heaven in a wild flower!')
archive.append(buffer3, {
    name: 'file3.txt'
})

// 追加一个文件
archive.file('test.pdf', {
    name: 'test2.pdf'
})

archive.finalize();
  • 解压文件和文件夹:
    方法1:第三方库unzipper
npm install unzipper
var fs = require('fs');
var unzipper = require('unzipper');

fs.createReadStream('../assets/test.zip')
    .pipe(unzipper.Parse())
    .on('entry', function (entry) {
        const fileName = entry.path;
        const type = entry.type; // 'Directory' or 'File'
        const size = entry.vars.uncompressedSize; // There is also compressedSize;

        console.log(type);
        if (type == 'Directory') {
            console.log('[DIR]', fileName, type);
            fs.mkdir(fileName, {
                recursive: true
            }, (err) => {
                if (err) throw err;
            });
            return;
        }

        console.log('[FILE]', fileName, type);
        entry.pipe(fs.createWriteStream(fileName));
        // NOTE: To ignore use entry.autodrain() instead of entry.pipe()
    });

在这里插入图片描述

方法2:第三方库unzip

npm install unzip
var fs = require("fs");
var unzip = require("unzip");

fs.createReadStream('archiver-unzip.zip').pipe(unzip.Extract({
    path: 'unarchive'
}));

4.8 处理docx/pptx/xlsx文档文件

officegen是自己绘制word格式:
https://www.npmjs.com/package/officegen

docxtemplater以模板替换的模式 :
https://docxtemplater.readthedocs.io/en/latest/installation.html

安装第三方库officegen:

npm install officegen

Creating Office Open XML files (Word, Excel and Powerpoint) for Microsoft Office 2007 and later without external tools, just pure Javascript. officegen should work on any environment that supports Node.js including Linux, OSX and Windows. officegen also supporting PowerPoint native charts objects with embedded data.

相关代码如下:

//***********************************************************************
//   Purpose:   基于nodejs生成docx文档文件
//   Author:    爱看书的小沐
//   Date:      2022-4-3
//   Languages: javascript
//   Platform:  nodejs 16.14.0 win64
//   OS:        Win10 win64
// ***********************************************************************

const fs = require('fs')
const officegen = require('officegen')

module.exports = {
    create_word: async () => {

        //创建word对象
        let docx = officegen('docx');

        docx.on('finalize', function (written) {
            console.log('这里成功创建了一个word文件.')
        })

        docx.on('error', function (err) {
            console.log(err)
        })

        // 创建第一段文字
        let pObj = docx.createP();
        pObj.addText('This is a first text.');
        pObj.addLineBreak();
        pObj.addText('长安一片月,万户捣衣声。');
        pObj.addLineBreak();
        pObj.addText('秋风吹不尽,总是玉关情。');
        pObj.addLineBreak();
        pObj.addText('何日平胡虏,良人罢远征。');
        pObj.addLineBreak();

        // 创建第二段文字,设置颜色
        pObj = docx.createP();
        pObj.addText('This is a two text with color', {
            color: '00FF00'
        })
        pObj.addText(' and back color.', {
            color: '00ffff',
            back: '000088'
        })
        pObj.addText(' and highlight color', {
            highlight: true
        })
        pObj.addText(' and highlight color2', {
            highlight: 'darkGreen'
        })
        pObj.addLineBreak();

        pObj.addText('主人有酒欢今夕,请奏鸣琴广陵客。', {
            color: '00FF00'
        });
        pObj.addLineBreak();
        pObj.addText('月照城头乌半飞,霜凄万木风入衣。', {
            color: '00FFFF'
        });
        pObj.addLineBreak();
        pObj.addText('铜炉华烛烛增辉,初弹渌水后楚妃。', {
            color: '0000FF'
        });
        pObj.addLineBreak();
        pObj.addText('一声已动物皆静,四座无言星欲稀。', {
            color: 'FFFF00'
        });
        pObj.addLineBreak();
        pObj.addText('清淮奉使千余里,敢告云山从此始。', {
            color: 'FF00FF'
        });
        pObj.addLineBreak();

        // 创建第三段文字,设置网络链接
        pObj = docx.createP()
        pObj.addText('This is a three text with ')
        pObj.addText('external link', {
            link: 'https://www.csdn.net'
        })

        // 创建第四段文字,加粗
        pObj = docx.createP()
        pObj.addText('This is a four text with Bold + underline', {
            bold: true,
            underline: true
        })

        // 创建第五段文字,居中
        pObj = docx.createP({
            align: 'center'
        })
        pObj.addText('This is a five text with center this text', {
            border: 'dotted',
            borderSize: 12,
            borderColor: '88CCFF'
        })

        // 创建第六段文字,右对齐
        pObj = docx.createP()
        pObj.options.align = 'right'
        pObj.addText('This is a six text with align this text to the right.')

        // 执行分页操作
        docx.putPageBreak()

        // 创建第七 段文字,
        pObj = docx.createP()
        pObj.addText('言入黄花川,每逐青溪水。', {
            font_face: 'Arial'
        })
        pObj.addText('随山将万转,趣途无百里。', {
            font_face: 'Arial',
            font_size: 40
        })

        // 执行分页操作
        docx.putPageBreak()

        // 创建图片对象,
        pObj = docx.createP()
        pObj.addImage('../assets/test.jpg')
        pObj.addImage('../assets/contributors_1.png')

        // 执行分页操作
        docx.putPageBreak()

        // 添加表格
        let tableStyle = {
            tableColWidth: 2500,
            tableSize: 60,
            tableColor: "blue",
            tableAlign: "center",
            tableVAlign: "center",
            tableFontFamily: "Arial",
            borders: true
        }
        let table = [
            [{
                val: '姓名',
                opts: {
                    align: "center",
                    vAlign: "center",
                    sz: '40',
                }
            }, {
                val: '学校',
                opts: {
                    align: "center",
                    vAlign: "center",
                    sz: '35',
                }
            }, {
                val: '年龄',
                opts: {
                    align: "center",
                    vAlign: "center",
                    sz: '35',
                }
            }]
        ]

        let student1 = ['戈戈', '北京大学', 12]
        let student2 = ['狄狄', '清华大学', 25]
        let student3 = ['可乐', '社会大学', 32]
        table.push(student1, student2)
        docx.createTable(table, tableStyle)

        // 保存docx文件
        let out = fs.createWriteStream('test.docx')

        out.on('error', function (err) {
            console.log(err)
        })

        docx.generate(out)
    }
}
const word = require('./server4_word')
word.create_word()

在这里插入图片描述
官网代码处理ppt如下:

const officegen = require('officegen')
const http = require('http')

/**
 * This is a simple web server that response with a PowerPoint document.
 */
http.createServer(function(req, res) {
  // We'll send a generated on the fly PowerPoint document without using files:
  if (req.url == '/') {
    // Create an empty PowerPoint object:
    let pptx = officegen('pptx')

    // Let's create a new slide:
    var slide = pptx.makeNewSlide()

    slide.name = 'Hello World'

    // Change the background color:
    slide.back = '000000'

    // Declare the default color to use on this slide:
    slide.color = 'ffffff'

    // Basic way to add text string:
    slide.addText('Created on the fly using a http server!')

    //
    // Let's generate the PowerPoint document directly into the response stream:
    //

    res.writeHead(200, {
      'Content-Type':
        'application/vnd.openxmlformats-officedocument.presentationml.presentation',
      'Content-disposition': 'attachment filename=out-' + new Date().getTime() + '.pptx'
    })

	// Content types related to Office documents:
    // .xlsx   application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
    // .xltx   application/vnd.openxmlformats-officedocument.spreadsheetml.template
    // .potx   application/vnd.openxmlformats-officedocument.presentationml.template
    // .ppsx   application/vnd.openxmlformats-officedocument.presentationml.slideshow
    // .pptx   application/vnd.openxmlformats-officedocument.presentationml.presentation
    // .sldx   application/vnd.openxmlformats-officedocument.presentationml.slide
    // .docx   application/vnd.openxmlformats-officedocument.wordprocessingml.document
    // .dotx   application/vnd.openxmlformats-officedocument.wordprocessingml.template
    // .xlam   application/vnd.ms-excel.addin.macroEnabled.12
    // .xlsb   application/vnd.ms-excel.sheet.binary.macroEnabled.12

    // This one catch only the officegen errors:
    pptx.on('error', function(err) {
      res.end(err)
    })

    // Catch response errors:
    res.on('error', function(err) {
      res.end(err)
    })

    // End event after sending the PowerPoint data:
    res.on('finish', function() {
      res.end()
    })

    // This async method is working like a pipe - it'll generate the pptx data and pass it directly into the output stream:
    pptx.generate(res)
  } else {
    res.end('Invalid Request!')
  } // Endif.
}).listen(3000)

在这里插入图片描述

4.9 处理数据库sqlite3

https://github.com/mapbox/node-sqlite3

The sqlite3 module works with:

  • Node.js v11.x, v12.x, v13.x and v14.x.
  • Electron v6.0.x, v6.1.x, v7.0.x, v7.1.x, v8.0.x, v8.1.x and v8.2.x
  • (1)安装sqlite3库
//npm install sqlite3
npm install https://github.com/mapbox/node-sqlite3/tarball/master

在这里插入图片描述

  • (2)官网的sqlite3例子
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database(':memory:');

db.serialize(function() {
  db.run("CREATE TABLE lorem (info TEXT)");

  var stmt = db.prepare("INSERT INTO lorem VALUES (?)");
  for (var i = 0; i < 10; i++) {
      stmt.run("Ipsum " + i);
  }
  stmt.finalize();

  db.each("SELECT rowid AS id, info FROM lorem", function(err, row) {
      console.log(row.id + ": " + row.info);
  });
});

db.close();

在这里插入图片描述

  • (3)自己测试的sqlite3例子
//***********************************************************************
//   Purpose:   基于nodejs测试sqlite3
//   Author:    爱看书的小沐
//   Date:      2022-4-3
//   Languages: javascript
//   Platform:  nodejs v14.19.1 win64
//   OS:        Win10 win64
// ***********************************************************************

var fs = require('fs');
var sqlite3 = require('sqlite3');
var database_file = __dirname + '/test.db';

fs.unlink(database_file, function (err) { 
    //if (err) throw err; 
    console.log('File deleted!'); 
 });

var db = new sqlite3.Database(database_file,function() {
  db.run("create table t_user(name varchar(15), age int)",function(){
    db.run("insert into t_user values('爱看书的小沐', 16)",function(){
      db.all("select * from t_user",function(err,res){
        if(!err)
          console.log(JSON.stringify(res));
        else
          console.log(err);
      });
    })
  });
});
db.close();

在这里插入图片描述

  • (4)增删查改

// Run Create Table
db.run(`create table t_user (id INT,name VARCHAR,password VARCHAR)`, function (
    err
) {
    if (err) throw err;
    console.log("Create Table Success!");
});

// Run Insert Data
db.run(`insert into t_user values (1,"admin","admin")`, function (err) {
    if (err) throw err;
    console.log("Insert Data Success!");
});

// Run Update Data
db.run(`update t_user set name = "guest" WHERE id = 1`, function (err) {
    if (err) throw err;
    console.log("Update Data Success!");
});

// Run Delete Data
db.run(`delete from t_user WHERE id = 1`, function (err) {
    if (err) throw err;
    console.log("Delete Data Success!");
});

// Run Drop Table
db.run(`drop table t_user`, function (err) {
    if (err) throw err;
    console.log("Drop Table Success!");
});
  • (5)其他命令
npm cache clean -f
npm uninstall node-gyp -g
npm install node-gyp -g
npm cache clean sqlite3
//管理员cmd执行
npm install --global --production windows-build-tools

4.10 处理视频文件

例子1:

  • server4_video.js:
var http = require('http');
var fs = require('fs');
var url = require('url');

http.createServer(function (request, response) {
    //获取当前访问网址
    var pathname = url.parse(request.url).pathname;
    console.log("url: " + pathname);
    if (pathname == "/") {
        pathname = "/index.html";
    }
    
    //构建完整本地路径
    var pathname_full = __dirname + decodeURI(pathname);
    console.log("request: " + pathname_full);

    //获取文件的扩展名
    var ext = pathname.match(/(\.[^.]+|)$/)[0];
    console.log("ext: " + ext);

    //根据不同的文件扩展名做出不同的处理
    if(ext == ".mp4" || ext == ".webm") {
        fs.exists(pathname_full, function (exists) {
            if (exists) {
                response.writeHead(200, {
                    'Content-Type': 'video/mp4'
                });
                var stream = fs.createReadStream(pathname_full).on("open", function () {
                    stream.pipe(response); 
                }).on("error", function (err) {
                    response.end(err);
                }); 
    
            } else {
                console.log(pathname_full + " 文件不存在!");
                response.writeHead(404, {
                    "Content-Type": "text/plain"
                });
                response.end(pathname + " 文件不存在!");
            }
        });
    }
    else {
        fs.readFile('.' + pathname, 'utf-8', function (err, data) {
            response.writeHead(200, {
                "Content-Type": "text/html"
            });
            response.write(data);
            response.end();
        });
    }
    
}).listen(3000);

console.log('Server running at http://127.0.0.1:3000/');
  • index.html:
<html>
  <title>Welcome</title>
    <body>
      <video controls>
        <source src="golden-dark.mp4" type="video/mp4"/>
        <source src="controller_update_controllerhud.webm" type="video/webm"/>
        <!-- fallback -->
        Your browser does not support the <code>video</code> element.
    </video>
    <video width="320" height="240" controls="controls">
      <source src="controller_update_controllerhud.webm" type="video/webm"/>
  </video>
  </body>
</html>

在这里插入图片描述
在这里插入图片描述

例子2:

  • server4_video2.js:
var http = require('http');
var fs = require('fs');
var url = require('url'); 
var router = require('./router.js');

http.createServer(function (request, response) {
    var pathname = url.parse(request.url).pathname;
    if (pathname == "/") {
        pathname = "/index.html";
    }
    
    fs.exists(__dirname + decodeURI(pathname), function (exists) {
        if (exists) {
            router.readFileByExt(pathname, fs, request, response);
        } else {
            console.log(decodeURI(pathname) + " not exist!");
            response.writeHead(404, {
                "Content-Type": "text/plain"
            });
            response.end(pathname + " not exist!");
        }
    });
}).listen(3000);

console.log('Server running at http://127.0.0.1:3000/');
  • router.js:
const logToFile = function (fs, content) {
    fs.writeFile(__dirname + '/log.txt', content, err => {
      if (err) {
        console.error(err)
        return
      }
    })
}

const readFileByExt = function (pathname, fs, request, response) {
    var ext = pathname.match(/(\.[^.]+|)$/)[0];
    switch (ext) {
        case ".css":
        case ".txt":
        case ".js":
        case ".json":
        case ".xml":
        case ".pdf":
        case ".docx":
            fs.readFile("." + request.url, 'utf-8', function (err, data) {
                if (err) throw err;
                response.writeHead(200, {
                    "Content-Type": {
                        ".css": "text/css",
                        ".txt": "text/plain",
                        ".js": "application/javascript",
                        ".json": "application/json",
                        ".xml": "application/xml",
                        ".pdf": "application/pdf",
                        ".docx": "application/msword",
                    } [ext]
                });
                response.write(data);
                response.end();
            });
            break;
            case ".bmp":
        case ".jpg":
        case ".gif":
        case ".png":
            fs.readFile("." + decodeURI(request.url), 'binary', function (err, data) {
                if (err) throw err;
                response.writeHead(200, {
                    "Content-Type": {
                        ".bmp": "image/bmp",
                        ".jpg": "image/jpeg",
                        ".gif": "image/gif",
                        ".png": "image/png",
                    } [ext]
                });
                response.write(data, 'binary');
                response.end();
            });
            break;
        case ".rar":
        case ".zip":
        case ".7z":
            var stats = fs.statSync("." + decodeURI(request.url));
            response.writeHead(200, {
                "Content-Type": "application/octet-stream", //相应该文件应该下载
                "Content-Disposition": `attachment; filename = ${pathname.replace("/","")}`,
                "Content-Length": stats.size
            });
            fs.createReadStream("." + decodeURI(request.url)).pipe(response);
            break;
        case ".mp4":
            fs.stat('.' + decodeURI(request.url), function (err, stats) {
                if (err) {
                    if (err.code === 'ENOENT') {
                        return 404;//return response.sendStatus(404);
                    }
                    response.end(err);
                }
                
                var range = request.headers.range;
                console.log(request.headers);
                console.log(range);
                if (!range) {
                    return 416;//return response.sendStatus(416);
                }
                //替换、切分,请求范围格式为:Content-Range: bytes 0-2000/4932
                var positions = range.replace(/bytes=/, "").split("-");
                var start = parseInt(positions[0]);
                var total = stats.size;
                var end = positions[1] ? parseInt(positions[1], 10) : total - 1;
                var chunksize = (end - start) + 1;

                response.writeHead(206, {
                    "Content-Range": "bytes " + start + "-" + end + "/" + total,
                    "Accept-Ranges": "bytes",
                    "Content-Length": chunksize,
                    "Content-Type": "video/mp4"
                });
                
                var stream = fs.createReadStream('.' + decodeURI(request.url), {
                        start: start,
                        end: end
                    })
                    .on("open", function () {
                        stream.pipe(response); 
                    }).on("error", function (err) {
                        response.end(err);
                    });
            });
            break;
        default:
            fs.readFile('.' + pathname, 'utf-8', function (err, data) {
                response.writeHead(200, {
                    "Content-Type": "text/html"
                });
                response.write(data);
                response.end();
            });
    }
}

exports.readFileByExt = readFileByExt
  • index.html:
<html>
  <title>Welcome</title>
    <body>
      <video controls>
        <source src="golden-dark.mp4" type="video/mp4"/>
        <source src="controller_update_controllerhud.webm" type="video/webm"/>
        <!-- fallback -->
        Your browser does not support the <code>video</code> element.
    </video>
  </body>
</html>

在这里插入图片描述
在这里插入图片描述

后记

如果你觉得该方法或代码有一点点用处,可以给作者点个赞、赏杯咖啡;╮( ̄▽ ̄)╭
如果你感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进。o_O???
谢谢各位童鞋们啦( ´ ▽´ )ノ ( ´ ▽´)っ!!!


  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值