NodeJS缓存机制:畅销货,就多囤一点呗

   2023-02-09 学习力0
核心提示:上一篇文章,我们已经实现了客户端向NodeJS服务器发出请求时,服务器从磁盘读取文件内容后,向客户端返回文件的数据。而对于爱莲(iLinkIT)的1对n的场景,即将文件共享出来之后,让多个用户同时下载,如果每个用户发起请求,我们都重新去磁盘读一下文件,那样

上一篇文章,我们已经实现了客户端向NodeJS服务器发出请求时,服务器从磁盘读取文件内容后,向客户端返回文件的数据。而对于爱莲(iLinkIT)的1对n的场景,即将文件共享出来之后,让多个用户同时下载,如果每个用户发起请求,我们都重新去磁盘读一下文件,那样岂不是效率低下?本文将重点改进一下效率和体验的问题。

老规矩,先上一个图:

NodeJS缓存机制:畅销货,就多囤一点呗

因为对于一个具体的共享任务,文件是同一个的,我们可以只做一次读取文件的操作,把读取进来的文件数据先保存到缓冲区。当有客户端发送请求时,就从缓冲区读取数据响应对应的客户端。

代码如下:

 1 var http = require( 'http' );
 2 var fs = require('fs');
 3 
 4 var file_path = "D:\\ilinkit_logo.png" ;
 5 var file_stream ;
 6 var buffer_box = [] ;
 7 var file_length = 0 ; 
 8 
 9 fs.stat( file_path , function ( err , stat ){
10             if (err) {
11                 if ('ENOENT' == err.code) {
12                     console.log( 'File does not exist...' );
13                 } else {
14                     console.log( 'Read file exception...' );
15                 }
16             } else {
17                 file_stream = fs.createReadStream( file_path );      
18                 file_stream.on( 'data' , function( chunk ){
19                     buffer_box.push( chunk ) ;
20                     file_length += chunk.length ;
21                 } ); 
22                 file_stream.on( 'end' , function(  ){
23                     console.log( "文件读取完毕" );
24                 } );
25                 file_stream.on('error', function(err){
26                     console.log( "文件读取失败!" );
27                 }); 
28                 
29                 var server =http.createServer( function ( request ,response ){
30                     for( var buffer_index = 0 ; buffer_index<buffer_box.length ; buffer_index++ )
31                     {
32                         response.write( buffer_box[buffer_index] );
33                     }
34                     response.end();
35                 } );
36                 server.listen( 8000 );
37                 console.log( 'HTTP服务器启动中,端口:8000.....' );
38                 
39             }//end else,读取文件没有发生错误
40 });                 

先解释一下整体的框架调整。从第9行~第40行,都是用fs.stat检查文件的相关信息,如果文件存在不存在,或者其他异常(例如:当前用户无权限读取该文件等。),就什么也不做,退出程序。如果读取文件正确,则创建一个HTTP服务器(第29行~第36行)。

关键代码解析如下:

第6行和第7行,声明保存文件数据的缓冲区的相关变量。

第19行和第20行,将文件的数据保存到缓冲区中。

第30行~第34行,当有客户端有发送请求时,从缓冲区读取数据,通过response对象向客户端传送数据。

 

验证方式如下:

1. 启动服务器:打开命令行,进入js脚本所在的位置,执行:node f_ilinkit_1.js

2. 打开浏览器,输入:http://localhost:8000,显示如下:

NodeJS缓存机制:畅销货,就多囤一点呗

改进1

建立了缓冲区,客户端提交请求之后,直接从缓冲区返回数据,貌似整个过程已经很完美了,但是,其实,咱们的程序还存在致命的问题。我们在向客户端响应数据的时候,是非常简单地调用 response.write( buffer_box[buffer_index] ); 来响应,但是,知道HTTP协议的同学都知道,如果用Web服务器的标准来看,客户端和服务器之间的响应,是还需要进行“响应头”的设置的,这样,客户端才知道接收到的数据是什么类型?应该如何处理?

因为我们之前用来测试的文件是D:\ilinkit_logo.png,客户端(浏览器)接收到一个图片的文件之后,就把它显示在浏览器中了,如果我们共享的文件是zip文件,是rar文件,会发生什么呢?所以,服务器在向客户端发送数据时,应该设置“响应头”的内容,让客户端把当前的数据当作一个附件来处理,这也符合我们爱莲(iLinkIT)的业务场景。改进后的代码如下:

 1 var http = require( 'http' );
 2 var fs = require('fs');
 3 
 4 var file_path = "D:\\ilinkit_logo.rar" ;
 5 var file_stream ;
 6 var buffer_box = [] ;
 7 var file_length = 0 ; 
 8 
 9 var file_name = file_path.substr( file_path.lastIndexOf('\\')+1 );
10 
11 fs.stat( file_path , function ( err , stat ){
12             if (err) {
13                 if ('ENOENT' == err.code) {
14                     console.log( 'File does not exist...' );
15                 } else {
16                     console.log( 'Read file exception...' );
17                 }
18             } else {
19                 file_stream = fs.createReadStream( file_path );      
20                 file_stream.on( 'data' , function( chunk ){
21                     buffer_box.push( chunk ) ;
22                     file_length += chunk.length ;
23                 } ); 
24                 file_stream.on( 'end' , function(  ){
25                     console.log( "文件读取完毕" );
26                 } );
27                 file_stream.on('error', function(err){
28                     console.log( "文件读取失败!" );
29                 }); 
30                 
31                 var server =http.createServer( function ( request ,response ){
32                     response.setHeader( 'Content-Type' , 'application/octet-stream' );
33                     response.setHeader( 'Content-Disposition' , 'attachment; filename=' + encodeURIComponent(file_name) );
34                     
35                     for( var buffer_index = 0 ; buffer_index<buffer_box.length ; buffer_index++ )
36                     {
37                         response.write( buffer_box[buffer_index] );
38                     }
39                     response.end();
40                 } );
41                 server.listen( 8000 );
42                 console.log( 'HTTP服务器启动中,端口:8000.....' );
43                 
44             }//end else,读取文件没有发生错误
45 });                 

关键的改进点说明如下:

第4行,共享的文件,我们把ilinkit_logo.png修改为ilinkit_logo.rar。当然,在D:下应该放一个ilinkit_logo.rar的文件。

第9行,我们从共享的文件路径中,解析出文件名(例子中就是:ilinkit_logo.rar),用于向客户端响应时,告知当前附件的文件名。

第32行和第33行,在向客户端提供文件数据之前,先设置响应的内容的类型(Content-Type)和内容特点(Content-Disposition),告诉客户端,要将接收到数据当附件处理,文件名为ilinkit_logo.rar。

验证方式如下:

1. 先将ilinkit_logo.png压缩成ilinkit_logo.rar,压缩后的文件依然放到D:下面。

2. 启动服务器:打开命令行,进入js脚本所在的位置,执行:node f_ilinkit_2.js

3. 打开浏览器,输入:http://localhost:8000,显示如下:

NodeJS缓存机制:畅销货,就多囤一点呗

我们服务器里提供的共享文件是ilinkit_logo.rar,所以,用客户端访问,服务器就向客户端响应一个附件文件,其实,上面的代码中,我们如果把ilinkit_logo.rar修改为ilinkit_logo.png,浏览器收到文件数据之后,仍然会把它当“附件”处理,而不会显示在浏览器中,因为我们设置了响应头的内容。

共享文件修改为ilinkit_logo.png的时候,浏览器下载效果如下:

NodeJS缓存机制:畅销货,就多囤一点呗

【要点回顾】

今天的解说就到这里,我们一起来回顾一下要点:

1. 改进了响应数据的方式,将要共享的文件先读取到缓冲区,提高响应效率。

2. 通过设置“响应头”,告知客户端要将接收到的数据,当“附件”处理。

感谢诸位捧场,欢迎多提宝贵建议,谢谢^_^~~

 

-----------------------爱莲(iLinkIT)系列文章------------------------------------------

 缘起爱莲:我要的,现在就要!

爱莲(iLinkIT)的架构与原理

遇见NodeJS:JavaScript的贵人

NodeJS服务器:一行代码 = 一个的HTTP服务器

NodeJS文件读取:感恩常在--抓把糖果,愉悦客人

NodeJS缓存机制:畅销货,就多囤一点呗

NodeJS安全设计:好吃的草莓味糖果,只给好朋友小红

NodeJS服务器退出:完成任务,优雅退出

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • 打造自己的 nodejs 静态文件服务器(帖子内容,
    用NodeJS打造你的静态文件服务器在《The Node Beginner Book》的中文版(http://nodebeginner.org/index-zh-cn.html)发布之后,获得国内的好评。也有同学觉得这本书略薄,没有包含进阶式的例子。@otakustay同学说:“确实,我的想法是在这之上补一个简单的MV
    02-10
  • NodeJS无所不能:细数10个令人惊讶的NodeJS开源
    在几年的时间里,NodeJS逐渐发展成一个成熟的开发平台,吸引了许多开发者。有许多大型高流量网站都采用NodeJS进行开发,像PayPal,此外,开发人员还可以使用它来开发一些快速移动Web框架。  除了Web应用外,NodeJS也被应用在许多方面,本文盘点了NodeJS在其
    02-10
  • Linux环境下的Nodejs linux安装基本环境
    最近在学习Node.js,在window下总是觉得不那么爽快。最简单而且环保的方法是在虚拟机中安装一个Linux。 { 1.Linux:家中的Linux为Centos。 2.VirtuallyBox: 开启2块网卡。第一个选Host-Only目的是为了让虚拟机通上网。第二块选Bridge Adapter,这是为了
    02-09
  • nodejs package.json说明
    {"name": "test", //项目名称(必须),由小写英文字母、数字和下划线,不能含空格"version": "1.0.0", //项目版本(必须)"description": "This is for study gulp project !", //项目描述(必须)"homepage": "", //项目主页url " key
    02-09
  • 017 nodejs取参四种方法req.body,req.params,re
    摘要: nodejs取参四种方法req.body,req.params,req.param,req.body 获取请求很中的参数是每个web后台处理的必经之路,nodejs提供了四种方法来实现。获取请求很中的参数是每个web后台处理的必经之路,nodejs的 express框架 提供了四种方法来实现。req.bodyre
    02-09
  • Docker windows下安装并搭建Nodejs的webapp
    Docker windows下安装并搭建Nodejs的webapp
    一、关于Docker什么是Docker?Docker 采用go语言编写,是一个开源的应用容器引擎。让开发者可以快速打包他们的应用以及依赖包到一个封装的可移植的容器Image中,然后发布到任何流行的机器( Linux ,windows,Mac等)上,也可以实现虚拟化。容器是使用完全
    02-09
  • Nodejs+Express+Mysql实现简单用户管理增删改查
    Nodejs+Express+Mysql实现简单用户管理增删改查
     源码地址  https://github.com/king-y/NodeJs/tree/master/user目录结构  mysql.jsvar mysql = require('mysql');var pool = mysql.createPool({host : '127.0.0.1',user : 'root',password : '',database : 's79'});exports.que
    02-09
  • nodejs查看本机hosts文件域名对应ip
    const dns = require('dns')dns.lookup('domainName', function(err, result) {console.log(result)}) related:https://***.com/questions/36689536/how-to-resolve-hostname-to-an-ip-address-in-node-js
    02-09
  • nodejs process.memoryUsage() rss等参数啥含义
    nodejs process.memoryUsage() rss等参数啥含义
    1 前言使用process.memoryUsage() ,然后可以得到一个对象如下:{ rss: 4935680,heapTotal: 1826816,heapUsed: 650472,external: 49879}  然而不知道rss是什么缩写,不知道其含义,网上找了一圈,多数都没说到点上,我这边就补充一下,也作为记录使用。2 
    02-09
  • nodejs工程拷贝后运行报module找不到问题
    工程文件夹通过复制黏贴到另外一个地方,运行后报错 “can`t find module 某某某”,查看原因:输入node 进入控制台,输入console.log(module.paths)查看当前nodejs查找module的路径,如果没有工程里的node_modules,通过module.paths.push加入,检查是否有效
    02-09
点击排行