注:本文并非完整准确的官方教程的译文,因此用词和行文也仅满足于个人复习的需要。请以原文为准:https://hapijs.com/tutorials/serving-files?lang=en_US
在 web 开发中,一种很常见的需求就是显示静态内容。比如一个网站上面的“关于我们”和“联系方式”等栏目,这些栏目上的内容比较固定,也较少变更,因此根本没必要用到什么数据库,往往只需简单的显示一个 html 页面再配点图片就行了。在 hapi 中应对这种需求很简单。
首先,安装一个名为 inert 的组件。在你项目的根目录下执行下列命令,以“非全局”的方式安装:
npm install --save inert
接下来我们看看具体的实现方法。
首先,假设我的练习项目的目录结构为:
.
├── package.json
├── public
│ ├── doom.jpg
│ └── doom3.jpg
└── server.js
目录 public 下的2张图片用作练习,随便找2张即可。其中 server.js 的内容为:
'use strict';
const Hapi = require('hapi');
const server = new Hapi.Server();
server.connection({ port: 3000, host: 'localhost' });
server.register(require('inert'), (err) => {
if (err) {
throw err;
}
server.route({
method: 'GET',
path: '/picture.jpg', //真实的图片名称叫什么不重要,访问时以这个名称为准。
handler: function (request, reply) {
reply.file('public/doom.jpg'); //无论是绝对路径还是相对路径都支持。
}
});
server.start((err) => {
if (err) {
throw err;
}
console.log('Server running at:', server.info.uri);
});
});
然后,访问 http://localhost:3000/picture.jpg 时如果能看到图片正常显示就说明成功了。
鉴于例子中的2个图片都放在 public 目录下,每次在 reply.file() 中写的时候都要带上“public”,这样不但麻烦,而且以后一旦需要将图片转移到其它目录下还要逐个修改。有没有可能统一设置这个 public 目录呢?答案是肯定的,hapi 提供的解决方案如下:
让我们调整一下 server.js 中的代码,如下:
'use strict';
const Path = require('path'); //引入了 path 组件
const Hapi = require('hapi');
const server = new Hapi.Server({
connections: {
routes: {
files: {
//这里表示只要在 route 配置中涉及到静态文件,就统一到 public 目录下寻找。
relativeTo: Path.join(__dirname, 'public')
}
}
}
});
//官方的教程中,大概是因为笔误的关系,在这里缺少了很关键的下面一句!害得我研究了一下午。
server.connection({ port: 3000, host: 'localhost' });
server.register(require('inert'), (err) => {
if (err) {
throw err;
}
server.route({
method: 'GET',
path: '/picture.jpg',
handler: function (request, reply) {
reply.file('doom.jpg'); //现在这里只需要写图片名称就行了
}
});
server.start((err) => {
if (err) {
throw err;
}
console.log('Server running at:', server.info.uri);
});
});
请注意上面代码中的注释,很好理解。然后再浏览一下 http://localhost:3000/picture.jpg,如果能看到图片正常显示就说明成功了。
其实,官方的这个例子除了教会我们一个省事的办法外,主要的用意是向我们展示了 new Hapi.Server() 时加入额外配置参数的方法。所有在 new Hapi.Server() 时设定的参数,将会应用到后续的所有地方,本例中就是应用到了所有的 route 上。
上面的 reply.file() 很好用,但是对于某些更为复杂的需求就无能为力了,为此 hapi 提供了更灵活的 file handler 方式。