整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

如何在 Node.js 中高效地读取文件?

面向服务器端 JavaScript 环境 Node.js 的开发中,处理文件读取至关重要,它是实现文件内容访问、分析和操作的关键步骤。这一功能对开发网络服务、日志审查系统、数据加工程序等多种软件非常有用。有了 Node.js 强大的文件处理能力,您可以毫不费力地读入文本、JSON、XML 等文件类型,以适合您的特定需求。

  • Node.js 是什么?Node.js 如何安装及如何配置环境?一文讲解

应用实例

文件读取在众多情景下发挥着不可或缺的作用,下面举几个例子:

  1. 载入配置: 读入程序的设置,例如数据库的接入信息,或是 API 的密钥。
  2. 分析日志: 查阅并研究软件产生的日志,以获取性能指标和定位问题。
  3. 处理上传: 在网络应用中处理用户上送的文件。
  4. 数据导入: 读入来自外部数据库的数据,进行后续加工或分析。
  5. 提供静态资源: 网络服务器需要读入并响应 HTML、CSS、JavaScript 等静态资源的请求。
  6. 格式转换: 把数据从一种格式(比如 CSV、XML)转换为另一种,以满足程序需要。现在让我们更详细地探讨在 Node.js 中如何执行文件读取。

概念与模块解説

在 Node.js 中读取文件,一般会涉及几个关键的模块:

  • fs 模块:这个 Node.js 标准的文件系统模块,负责所有文件操作。我们主要通过它提供的API来实现文件的读取。

文件读取的几种方法

1. 同步读取

同步读取会在文件全部读入前暂停程序的运行。以下是一个典型例子:

const fs = require('fs');

try {
  const content = fs.readFileSync('example.txt', 'utf8');
  console.log(content);
} catch (err) {
  console.error(err);
}

2. 异步读取

异步操作允许程序继续执行,文件读取结束时通过回调函数进行处理:

const fs = require('fs');

fs.readFile('example.txt', 'utf8', (error, content) => {
  if (error) {
    console.error(error);
    return;
  }
  console.log(content);
});

3. 利用 Promises 进行读取

从 Node.js v12 开始,fs.promises API 加入,提供了基于 Promise 的读取方法:

const fsp = require('fs').promises;

fsp.readFile('example.txt', 'utf8')
  .then(content => {
    console.log(content);
  })
  .catch(err => {
    console.error(err);
  });

实操示例

我们使用一个具体的例子,演示在 Node.js 如何读取并处理文件。假定我们有一个名叫 data.txt 的文件,里面存有些许数据,我们想通过 Node.js 来读取它。

步骤 1: 准备文件

开始前,我们创建一个 data.txt 文件,内容如下:

Hello, Node.js!
Here is some example text.
We will read this file with Node.js.

步骤 2: 编写 Node.js 脚本

接下来,撰写一个简单的 Node.js 脚本文件来处理 data.txt

const fsp = require('fs').promises;

async function processFile() {
  try {
    const content = await fsp.readFile('data.txt', 'utf8');
    console.log('Read file successfully:\n', content);
  } catch (err) {
    console.error('An error occurred:', err);
  }
}

processFile();

这个脚本利用 fs.promises.readFile 异步读取文件,并通过 await 等待操作的完成。读取成功便输出文件内容,失败则打印错误信息。

步骤 3: 执行脚本

在终端中切回含有 Node.js 脚本与 data.txt 的目录,执行脚本:

node your-script.js

脚本将输出 data.txt 的内容到控制台上。

一些额外建议

  • 面对大型文件时,应优先考虑异步方法以避免执行阻塞。
  • 总是对可能遇到的异常情况做出处理,如文件缺失或无权访问。
  • 当处理非文本文件(比如图片或二进制文件)时,可跳过字符编码的设置以返回二进制数据。
  • 在处理大文件时,可考虑流式读取来降低内存占用。

用 Apifox 来管理后端接口

如果你是一名 Node.js 开发者,经常需要与后端 API 相互作用,确认应用的正确性。这时,一个有效的接口管理工具是必不可少的。

Apifox 提供了一套接口管理解决方案,它结合了 Postman 的调试功能以及 Swagger 的接口文档管理,附加 Mock 数据与 JMeter 性能测试,支持多种协议,如 HTTP(S)、WebSocket、Socket、gRPC、Dubbo 等,是为 API 开发着手设计的。此外,Apifox 还提供了 IDEA 插件,增强与 IDE 的协作效率。Apifox 的直观界面和全面功能,极大提高了项目开发的流程效率,可以让开发者更加方便地管理和测试接口。值得一试。

结语

在 Node.js 中,文件读取是一个基础且核心的操作,它使我们能够读入、分析和操作各种文件。本文介绍了几种常用的文件读取方式,并以实际实例指导了如何读取文本文件。希望以上内容能助您在 Node.js 项目中更高效地运用文件读取功能。

知识扩展:

  • Node.js 中如何设置定时任务?
  • Node.js 中如何删除文件?

参考链接:

  • Node.js fs 模块文档:https://nodejs.org/api/fs.html
  • Node.js fs.promises 模块文档:https://nodejs.org/api/fs.html#fs_promises_api



在前面

今年国庆假期终于可以憋在家里了不用出门了,不用出去看后脑了,真的是一种享受。这么好的光阴怎么浪费,睡觉、吃饭、打豆豆这怎么可能(耍多了也烦),完全不符合我们程序员的作风,赶紧起来把文章写完。

这篇文章比较基础,在国庆期间的业余时间写的,这几天又完善了下,力求把更多的前端所涉及到的关于文件上传的各种场景和应用都涵盖了,若有疏漏和问题还请留言斧正和补充。

自测读不读

以下是本文所涉及到的知识点,break or continue ?

  • 文件上传原理
  • 最原始的文件上传
  • 使用 koa2 作为服务端写一个文件上传接口
  • 单文件上传和上传进度
  • 多文件上传和上传进度
  • 拖拽上传
  • 剪贴板上传
  • 大文件上传之分片上传
  • 大文件上传之断点续传
  • node 端文件上传

原理概述

原理很简单,就是根据 http 协议的规范和定义,完成请求消息体的封装和消息体的解析,然后将二进制内容保存到文件。

我们都知道如果要上传一个文件,需要把 form 标签的enctype设置为multipart/form-data,同时method必须为post方法。

那么multipart/form-data表示什么呢?

multipart互联网上的混合资源,就是资源由多种元素组成,form-data表示可以使用HTML Forms 和 POST 方法上传文件,具体的定义可以参考RFC 7578。

multipart/form-data 结构

看下 http 请求的消息体



  • 请求头:

Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryDCntfiXcSkPhS4PN 表示本次请求要上传文件,其中boundary表示分隔符,如果要上传多个表单项,就要使用boundary分割,每个表单项由———XXX开始,以———XXX结尾。

  • 消息体- Form Data 部分

每一个表单项又由Content-Type和Content-Disposition组成。

Content-Disposition: form-data 为固定值,表示一个表单元素,name 表示表单元素的 名称,回车换行后面就是name的值,如果是上传文件就是文件的二进制内容。

Content-Type:表示当前的内容的 MIME 类型,是图片还是文本还是二进制数据。

解析

客户端发送请求到服务器后,服务器会收到请求的消息体,然后对消息体进行解析,解析出哪是普通表单哪些是附件。

可能大家马上能想到通过正则或者字符串处理分割出内容,不过这样是行不通的,二进制buffer转化为string,对字符串进行截取后,其索引和字符串是不一致的,所以结果就不会正确,除非上传的就是字符串。

不过一般情况下不需要自行解析,目前已经有很成熟的三方库可以使用。

至于如何解析,这个也会占用很大篇幅,后面的文章在详细说。

最原始的文件上传

使用 form 表单上传文件

在 ie时代,如果实现一个无刷新的文件上传那可是费老劲了,大部分都是用 iframe 来实现局部刷新或者使用 flash 插件来搞定,在那个时代 ie 就是最好用的浏览器(别无选择)。

DEMO



这种方式上传文件,不需要 js ,而且没有兼容问题,所有浏览器都支持,就是体验很差,导致页面刷新,页面其他数据丢失。

HTML

 <form method="post" action="http://localhost:8100" enctype="multipart/form-data">

        选择文件:
            <input type="file" name="f1"/> input 必须设置 name 属性,否则数据无法发送<br/>
<br/>
            标题:<input type="text" name="title"/><br/><br/><br/>

        <button type="submit" id="btn-0">上 传</button>

</form>

复制代码

文件上传接口

服务端文件的保存基于现有的库koa-body结合 koa2实现服务端文件的保存和数据的返回。

在项目开发中,文件上传本身和业务无关,代码基本上都可通用。

在这里我们使用koa-body库来实现解析和文件的保存。

koa-body 会自动保存文件到系统临时目录下,也可以指定保存的文件路径。



然后在后续中间件内得到已保存的文件的信息,再做二次处理。

  • ctx.request.files.f1 得到文件信息,f1为input file 标签的 name
  • 获得文件的扩展名,重命名文件

NODE

/**
 * 服务入口
 */
var http = require('http');
var koaStatic = require('koa-static');
var path = require('path');
var koaBody = require('koa-body');//文件保存库
var fs = require('fs');
var Koa = require('koa2');

var app = new Koa();
var port = process.env.PORT || '8100';

var uploadHost= `http://localhost:${port}/uploads/`;

app.use(koaBody({
    formidable: {
        //设置文件的默认保存目录,不设置则保存在系统临时目录下  os
        uploadDir: path.resolve(__dirname, '../static/uploads')
    },
    multipart: true // 开启文件上传,默认是关闭
}));

//开启静态文件访问
app.use(koaStatic(
    path.resolve(__dirname, '../static') 
));

//文件二次处理,修改名称
app.use((ctx) => {
    var file = ctx.request.files.f1;//得道文件对象
    var path = file.path;
    var fname = file.name;//原文件名称
    var nextPath = path+fname;
    if(file.size>0 && path){
        //得到扩展名
        var extArr = fname.split('.');
        var ext = extArr[extArr.length-1];
        var nextPath = path+'.'+ext;
        //重命名文件
        fs.renameSync(path, nextPath);
    }
    //以 json 形式输出上传文件地址
    ctx.body = `{
        "fileUrl":"${uploadHost}${nextPath.slice(nextPath.lastIndexOf('/')+1)}"
    }`;
});

/**
 * http server
 */
var server = http.createServer(app.callback());
server.listen(port);
console.log('demo1 server start ......   ');
复制代码

CODE

https://github.com/Bigerfe/fe-learn-code/

一篇:node.js 15 如何操作Excel文件

几乎所有的项目涉及到报表或者合同处理等,都会跟PDF打交道。


pdf

node.js中,用的比较多的是html-pdf,每周下载量达到8万多,是比较多了。


html-pdf

这款工具的特点是不光可以通过代码调用API生成pdf,还提供命令行工具html-pdf来将html文件转换成pdf文件。

接下来,我们看一下html-pdf的安装使用。

html-pdf 安装

 npm install -g html-pdf

由于html-pdf是基于phantomjs的,所以在安装过程中会自动下载phantomjs。

html-pdf命令行

html-pdf test/businesscard.html businesscard.pdf

直接运行html-pdf加上源html文件,后面加上pdf文件名就可以生成pdf文件。

创建PDF文件,代码示例

//引入fs, html-pef模块
var fs = require('fs');
var pdf = require('html-pdf');
//读取html文件
var html = fs.readFileSync('./test/businesscard.html', 'utf8');
//参数options, 将PDF format设为letter, 如果是A4,直接将下面代码中的letter换成A4即可
var options = { format: 'Letter' };

//创建pdf文件
pdf.create(html, options).toFile('./businesscard.pdf', function(err, res) {
  if (err) return console.log(err);
  console.log(res); // { filename: '/app/businesscard.pdf' }
});

相关API

var pdf = require('html-pdf');
pdf.create(html).toFile([filepath, ]function(err, res){
  console.log(res.filename);
});

pdf.create(html).toStream(function(err, stream){
  stream.pipe(fs.createWriteStream('./foo.pdf'));
});

pdf.create(html).toBuffer(function(err, buffer){
  console.log('This is a buffer:', Buffer.isBuffer(buffer));
});

HTML中的header 和footer可以直接读出

html-pdf 可以将html中的header和footer读出。只要是id为pageHeader或者pageFooter的都可以被识别出来。

<div id="pageHeader">Default header</div>
<div id="pageHeader-first">Header on first page</div>
<div id="pageHeader-2">Header on second page</div>
<div id="pageHeader-3">Header on third page</div>
<div id="pageHeader-last">Header on last page</div>
...
<div id="pageFooter">Default footer</div>
<div id="pageFooter-first">Footer on first page</div>
<div id="pageFooter-2">Footer on second page</div>
<div id="pageFooter-last">Footer on last page</div>

关于参数options

在调用API pdf.create(html, options).toFile()创建PDF时,这里面的参数options相当强大,可以传很多数据。包括之前说的A4格式。