node静态资源服务器的搭建----访问本地文件夹(搭建可访问静态文件的服务器)
我们的目标是实现一个可访问静态文件的服务器,即可以在浏览器访问文件夹和文件,通过点击来查看文件。
1.先创建一个文件夹anydoor,然后在该文件夹里npm init一个package.json文件,按如下图所示创建文件夹和文件(node_models,package-lock.json是安装生成,不用自己创建)。为了方便管理,我们把一些设置性和公共的参数放在defaultConfig.js里,方便后期的更改和管理,在app.js中创建一个服务器。
//app.js,(npm install chalk,chalk可以改变console打印的颜色)
const http = require('http');
const chalk = require('chalk');
const config = require('./config/defaultConfig.js');
var server = http.createServer(function(req,res){
res.statusCode = 200;
res.setHeader('Content-type','text/plain');
res.end('Hello world');
});
server.listen(config.port,config.hostname,()=>{
var addr = `http://${config.hostname}:${config.port}`;
console.info(`listenning in:${chalk.green(addr)}`);
})
这样,一个最简单的http服务器就就搭好了,在src文件夹中运行node app.js,如下图所示
在浏览器输入http://127.0.0.1:9527,打开控制台就可以看到请求,可以看到我们设置的参数。
2.接下来,我们着手搭建一个静态资源服务器,可以通过在浏览器地址栏输入地址的方式,访问启动当前服务的文件夹列表和文件夹的内容。在defaultConfig.js中添加一个新的配置项,root,当前node启动的目录。需要注意的是,process.cwd()是当前执行node命令时候的文件夹地址(工作目录),__dirname,是被执行的js 文件的地址 (文件所在目录)。
//defaultConfig.js
module.exports = {
root:process.cwd(),//process.cwd()是当前执行node命令时候的文件夹地址 ——工作目录,__dirname,是被执行的js 文件的地址 ——文件所在目录
hostname:'127.0.0.1',
port:9527
}
//app.js
const http = require('http');
const chalk = require('chalk');
const path = require('path');
const fs = require('fs');
const config = require('./config/defaultConfig.js');
var server = http.createServer(function(req,res){
const filePath = path.join(config.root,req.url)
console.info("path",`${chalk.green(filePath)}`)
fs.stat(filePath,(err,stats)=>{//fs.stat(path,callback),读取文件的状态;
if(err){//说明这个文件不存在
console.log(err)
res.statusCode = 404;
res.setHeader('Content-Type','text/javascript;charset=UTF-8');//utf8编码,防止中文乱码
res.end(`${filePath} is not a directory or file.`)
return;
}
if(stats.isFile()){//如果是文件
res.statusCode = 200;
res.setHeader('Content-Type','text/javascript;charset=UTF-8');
fs.createReadStream(filePath).pipe(res);//以流的方式来读取文件
}else if (stats.isDirectory()) {//如果是文件夹,拿到文件列表
fs.readdir(filePath,(err,files)=>{//files是个数组
res.statusCode = 200;
res.setHeader('Content-Type','text/plain');
res.end(files.join(','));//返回所有的文件名
})
}
})
});
server.listen(config.port,config.hostname,()=>{
var addr = `http://${config.hostname}:${config.port}`;
console.info(`listenning in:${chalk.green(addr)}`);
})
以我的本地文件为例,我的启动的app.js文件在“D:\studyCommon\anydoor\src”中,我在浏览器访问http://127.0.0.1:9527/,所以我的root就是D:\studyCommon\anydoor\src,src是文件夹,在浏览器看到的就是D:\studyCommon\anydoor\src里的文件列表。
同理,在浏览器中访问http://127.0.0.1:9527/app.js,root就是D:\studyCommon\anydoor\src\app.js,app.js是一个文件,浏览器看到的就是app.js的详细内容。
依次类推,当然还可以通过改变浏览器url查看config文件夹,以及config文件夹里的defaultConfig.js文件。
3.至此,一个静态资源服务器已经具备完整功能了,接下来我们优化,完善一下代码,也优化一下功能,让他看起来更高大上一些。现在代码有很多的异步回调,我们通过promisify改造一下代码,关于promise化可以看一下这篇博客https://blog.csdn.net/bdss58/article/details/67151775,然后也会用到async/await的知识点。
首先,将app.js改成如下形式
const http = require('http');
const chalk = require('chalk');
const path = require('path');
const fs = require('fs');
const promisify = require('util').promisify;
const stat = promisify(fs.stat);//stat方法promise化
const readdir = promisify(fs.readdir);
const config = require('./config/defaultConfig.js');
var server = http.createServer(function(req,res){
const filePath = path.join(config.root,req.url)
console.info("path",`${chalk.green(filePath)}`)
try{
fs.stat(filePath,(err,stats)=>{//fs.stat(path,callback),读取文件的状态;
if(stats.isFile()){//如果是文件
res.statusCode = 200;
res.setHeader('Content-Type','text/javascript;charset=UTF-8');
fs.createReadStream(filePath).pipe(res);//以流的方式来读取文件
}else if (stats.isDirectory()) {//如果是文件夹,拿到文件列表
fs.readdir(filePath,(err,files)=>{//files是个数组
res.statusCode = 200;
res.setHeader('Content-Type','text/plain');
res.end(files.join(','));//返回所有的文件名
})
}
})
}catch(err){
if(err){//说明这个文件不存在
console.log(err)
res.statusCode = 404;
res.setHeader('Content-Type','text/javascript;charset=UTF-8');//utf8编码,防止中文乱码
res.end(`${filePath} is not a directory or file.`)
return;
}
}
});
server.listen(config.port,config.hostname,()=>{
var addr = `http://${config.hostname}:${config.port}`;
console.info(`listenning in:${chalk.green(addr)}`);
})
接下来,promise化,以及把异步方法通过async/await改造成像是同步代码的样子(本质还是异步)。因为await方法必须在aysyn函数中使用,因此我们新建一个async的readFile函数。
const http = require('http');
const chalk = require('chalk');
const path = require('path');
const fs = require('fs');
const promisify = require('util').promisify;
const stat = promisify(fs.stat);//stat方法promise化
const readdir = promisify(fs.readdir);
const config = require('./config/defaultConfig.js');
var server = http.createServer(function(req,res){
const filePath = path.join(config.root,req.url)
console.info("path",`${chalk.green(filePath)}`)
async function readFile(req, res, filePath){
try{
const stats = await stat(filePath);//awit必须包含在async函数中,所以把所有代码移到定义的readFile函数中
if(stats.isFile()){//如果是文件
res.statusCode = 200;
res.setHeader('Content-Type','text/javascript;charset=UTF-8');
fs.createReadStream(filePath).pipe(res);//以流的方式来读取文件
}else if (stats.isDirectory()) {//如果是文件夹,拿到文件列表
//将readdir方法也promise化
const files = await readdir(filePath);
res.statusCode = 200;
res.setHeader('Content-Type','text/plain');
res.end(files.join(','));//返回所有的文件名
}
}catch(err){
res.statusCode = 404;
res.setHeader('Content-Type','text/javascript;charset=UTF-8');//utf8编码,防止中文乱码
res.end(`${filePath} is not a directory or file.`)
return;
}
}
readFile(req, res, filePath);//执行函数
});
server.listen(config.port,config.hostname,()=>{
var addr = `http://${config.hostname}:${config.port}`;
console.info(`listenning in:${chalk.green(addr)}`);
})
在浏览器地址栏依次输入http://127.0.0.1:9527,http://127.0.0.1:9527/app.js,http://127.0.0.1:9527/config,http://127.0.0.1:9527/config/defaultConfig.js,发现效果与原来的异步回调方法是一样的。为了代码结构更清晰,我们在src文件夹下新建helper文件夹,并创建一个readFile.js的文件,把readFile函数移动到这个文件里,并导入到app.js中。
//src/helper/readFile.js
const fs = require('fs');
const promisify = require('util').promisify;
const stat = promisify(fs.stat);//stat方法promise化
const readdir = promisify(fs.readdir);
module.exports = async function(req, res, filePath){
try{
const stats = await stat(filePath);//awit必须包含在async函数中,所以把所有代码移到定义的readFile函数中
if(stats.isFile()){//如果是文件
res.statusCode = 200;
res.setHeader('Content-Type','text/javascript;charset=UTF-8');
fs.createReadStream(filePath).pipe(res);//以流的方式来读取文件
}else if (stats.isDirectory()) {//如果是文件夹,拿到文件列表
//将readdir方法也promise化
const files = await readdir(filePath);
res.statusCode = 200;
res.setHeader('Content-Type','text/plain');
res.end(files.join(','));//返回所有的文件名
}
}catch(err){
console.log(err)
res.statusCode = 404;
res.setHeader('Content-Type','text/javascript;charset=UTF-8');//utf8编码,防止中文乱码
res.end(`${filePath} is not a directory or file.`)
return;
}
}
//app.js
const http = require('http');
const chalk = require('chalk');
const path = require('path');
const config = require('./config/defaultConfig.js');
const readFile = require('./helper/readFile.js');
var server = http.createServer(function(req,res){
const filePath = path.join(config.root,req.url)
console.info("path",`${chalk.green(filePath)}`)
readFile(req,res,filePath)
});
server.listen(config.port,config.hostname,()=>{
var addr = `http://${config.hostname}:${config.port}`;
console.info(`listenning in:${chalk.green(addr)}`);
})
至此,异步函数的同步写法改造就结束了,但是要访问某个文件夹还得自己在浏览器的地址栏里输入文件名,感觉很不方便,要是能点击页面上的文件名,然后直接跳转到对应文件就好了,接下来我们就实现这个功能。
4.我们可以通过html字符串拼接的方法来实现这个功能,将文件名的地址拼接在a标签中,点击a标签来实现跳转。因为要写入html标签,所以把Content-Type的Mime类型改为text/html。
//readFile.js
const fs = require('fs');
const promisify = require('util').promisify;
const stat = promisify(fs.stat);//stat方法promise化
const readdir = promisify(fs.readdir);
const config = require('../config/defaultConfig.js');
module.exports = async function(req, res, filePath){
try{
const stats = await stat(filePath);//awit必须包含在async函数中,所以把所有代码移到定义的readFile函数中
if(stats.isFile()){//如果是文件
res.statusCode = 200;
res.setHeader('Content-Type','text/javascript;charset=UTF-8');
fs.createReadStream(filePath).pipe(res);//以流的方式来读取文件
}else if (stats.isDirectory()) {//如果是文件夹,拿到文件列表
//将readdir方法也promise化
const files = await readdir(filePath);
res.statusCode = 200;
res.setHeader('Content-Type','text/html;charset=UTF-8');
res.write('<html><body><div>')
var html= '';
for(let i=0;i<files.length;i++){//
html+='<a style="display:block" href="http://127.0.0.1:9527'+
req.url+'/'+files[i]+'">'+files[i]+'</a>';
}
res.write(html);//返回所有的文件名
res.end('</div></body></html>')
}
}catch(err){
console.log(err)
res.statusCode = 404;
res.setHeader('Content-Type','text/javascript;charset=UTF-8');//utf8编码,防止中文乱码
res.end(`${filePath} is not a directory or file.`)
return;
}
}
现在,如下图所示,我们就可以自由的点击文件和文件名来实现访问,而不需要去地址栏输入地址了。
node静态资源服务器的搭建----访问本地文件夹(搭建可访问静态文件的服务器)的更多相关文章
- 访问静态资源有问题(配置url-pattern 用"/")(两种静态资源处理)
发起的请求是由哪些服务器程序处理的 http://localhost:8080/ch05_url_pattern/index.jsp: tomcat(jsp会转为servlet) http://loc ...
- 零基础学习java------39---------json格式交互,Restful(不懂),静态资源映射,SSM整合(ssm整合思想,application.xml文件详解(声明式事务管理),)
一. json格式交互(知道) 1 . 回顾ajax基本语法 $.ajax({ url:"", // 请求的后台路径 data:{"":"" ...
- express,node.js实现获取本地文件夹下面的全部图片文件
http://www.luyixian.cn/javascript_show_169354.aspx 按照网上的教程试了多次,处理了各种结果后还有报错, 最后的报错是cant find module ...
- [shell]用shell脚本将本地文件夹与ftp上的文件夹同步
需求说明 最近在AIX上做开发,开发机器在office网段,测试机器在lab网段,不能互相通讯,只能通过特定的ftp来传文件. 每次上传的机器都要做:登录ftp,进入我的目录,上传:下载的机器都要做: ...
- 将文件夹上传到FTP服务器,遍历上传,,,文件夹不能直接上传到FTP服务器上。。。
<? $ftp_ip = "FTP"; $ftp_user = "user"; $ftp_pwd = "password"; $con ...
- 将一个Linux系统中的文件或文件夹复制到另一台Linux服务器上(scp的使用)
一.复制文件: (1)将本地文件拷贝到远程scp 文件名 用户名@计算机IP或者计算机名称:远程路径(2)从远程将文件拷回本地scp 用户名@计算机IP或者计算机名称:文件名 本地路径 二.复制文件夹 ...
- 傲视Kubernetes(二):Docker镜像搭建与本地Kubernetes环境搭建
主要内容: 1.Docker与Kubernetes的关系 2.SpringBoot微服务的Docker镜像创建 3.Kubernetes本地环境搭建 一.Docker与Kubernetes的关系 在说 ...
- linux ftp服务器设置,只允许用户访问指定的文件夹,禁止访问其他文件夹
在Linux中添加ftp用户,并设置相应的权限,操作步骤如下: 1.环境:ftp为vsftp.被限制用户名为test.被限制路径为/home/test 2.建用户:在root用户下: useradd ...
- 127.0.0.1 拒绝了我们的连接请求--访问本地IP时显示拒绝访问
问题描述 今天在访问http://127.0.0.1时,浏览器显示"127.0.0.1 拒绝了我们的连接请求",需要设置浏览器设置 解决方法 1.打开控制面板,搜索"程序 ...
- centos的nginx如何访问本地共享文件夹的文件 nginx访问404,403问题
关键挂载 sudo vmhgfs-fuse .host:/musings /home/xxx -o allow_other,uid=0,gid=0
随机推荐
- 在最新的 create-react-app 中添加 less 支持
前置知识: 把 webpack 的相关配置暴露出来 运行 git add -A 运行 git commit -m 'project init' 运行 yarn eject 然后选 y 项目中多出来两个 ...
- Selenium 元素常用操作方法(键盘和鼠标事件)
一.简单操作 click():点击 send_keys():输入 clear():清空 submit():提交表单 size:返回元素的尺寸 text:获取元素的文本 get_attribute(): ...
- go语言系列--golang在windows上的安装和开发环境goland的配置
在windows上安装golang软件 golang中国网址为:https://studygolang.com/dl 我的学习选择版本:1.12.5 golang 1.12.5版本更新的内容:gola ...
- java 用redisTemplate 的 Operations存取list集合
一 .存取为list类型 @RestController @RequestMapping("/test") @Slf4j public class TestController { ...
- activemq 笔记
官网下载好后,修改下conf下activemq.xml配置文件就可以了. 主要将这里的ip改成我们这里用的locahost就可以了: <transportConnectors> <! ...
- Oracle JET mobile cordove navigator.app对象
在使用 Oracle JET 开发 webapp 时,会使用到 ojrouter ,ojrouter 默认含有历史记录推送功能.在调试 Android 时会发现返回键总是返回到上一次浏览记录(App ...
- fedora14 - 22安装yum源的最终所有唯一文档
yum的配置包括3个地方 /etc/yum中主要是yum的插件: /etc/yum/pluginconf.d 目录下配置yum的插件的启用或禁用等... /etc/yum.conf这个是yum的主要配 ...
- 阶段3 1.Mybatis_12.Mybatis注解开发_5 mybatis注解建立实体类属性和数据库表中列的对应关系
创建新项目,一对多 复制刚才关闭的项目的文件 复制到们的新项目里面 复制包的依赖 删减相关代码.只保留这三个查询的方法 模糊查询改成传统的占位符的方式 之前是可以自定义实体类的属性字段,和数据库的字典 ...
- 测开之路一百五十二:基于jquery的ajax实现之load、get、ajax
ajax除了用原生的js实现之外,也可以使用jquery实现,而且用jquery更方便 看一个简单的示例,保留上一篇的content路由和html,实现上一篇一样的功能,点击获取内容,局部刷新 准备一 ...
- java 上传文件到FTP(centos中的ftp服务)
ftp服务器系统:centos7 提供ftp的服务:vsftpd pom.xml 依赖 <dependency> <groupId>commons-net</groupI ...