Node手把手構建一個靜態檔案伺服器
這篇文章主要將會通過node手把手的構建一個靜態檔案伺服器,那麼廢話不多說,開發流程走起來,我們先看一下將要做的這個靜態檔案伺服器將會有哪些功能?
這個靜態檔案伺服器有哪些功能?
- 讀取靜態檔案
- MIME型別支援
- 支援壓縮
- 支援斷點續傳
- 支援快取與快取控制
- 實現命令列呼叫
- 最後將程式碼釋出到npm,可通過npm install -g全域性安裝
好了,通過以上的功能梳理,那麼我們需要實現的功能就很明確了,也就相當於我們專案開發過程中的需求現在已經確定了(原諒我這些天被公司專案別急了),接下來就一步步開始實現功能吧。
功能實現——讀取靜態檔案+MIME型別支援
首先先構建好專案目錄,專案目錄如下:
project |---bin 命令列實現放置指令碼 | |---public 靜態檔案伺服器預設靜態資料夾 | |---src 實現功能的相關程式碼 | | | |__template 模板資料夾 | | | |__app.js 主要功能檔案 | |__config.js 配置檔案 | |---package.josn (這個不用多說了吧)
然後開始實現功能,我們將會通過node的http模組來啟動一個服務,這裡我先將功能(讀取靜態檔案、MIME型別支援)的實現整體程式碼貼出來,再慢慢道來:
const http = require('http')
const path = require('path')
const url = require('url')
const fs = require('fs')
let chalk = require('chalk');
process.env.DEBUG = 'static:*';
let debug = require('debug')('static:app');//每個debug例項都有一個名字,是否在控制檯列印取決於環境變數中DEBUG的值是否等於static:app
const mime = require('mime');
const {promisify} = require('util')
let handlebars = require('handlebars');
const config = require('./config')
const stat = promisify(fs.stat)
const readDir = promisify(fs.readdir)
//獲取編譯模板
function getTemplet() {
let tmpl = fs.readFileSync(path.resolve(__dirname, 'template', 'list.html'), 'utf8');
return handlebars.compile(tmpl);
}
class Server {
constructor(argv) {
this.config = Object.assign({}, config, argv);
this.list = getTemplet();
}
//啟動服務
start() {
let server = http.createServer();
server.on('request', this.request.bind(this))
server.listen(this.config.port);
let url=`http://${this.config.host}:${this.config.port}`;
debug(`靜態服務啟動成功${chalk.green(url)}`);
}
async request(req, res) {//服務監聽函式
let pathName = url.parse(req.url).path;
let filePath = path.join(this.config.root, pathName);
if (filePath.indexOf('favicon.ico') > 0) {
this.sendError(req, res, 'not found');
return
}
try {//在靜態服務資料夾存在訪問的路徑內容
let statObj = await stat(filePath);
if (statObj.isDirectory()) {//是資料夾
let directories = await readDir(filePath);
let files = directories.map(file => {
return {
filename: file,
url: path.join(pathName, file)
}
});
let htmls = this.list({
title: pathName,
files
});
res.setHeader('Content-Type', 'text/html');
res.end(htmls);
} else {//是檔案
this.sendContent(req, res, filePath, statObj);
}
} catch (err) {//靜態伺服器內容不存在訪問內容
this.sendError(req, res, err);
}
}
sendContent(req, res, filePath, statObj) {//向客戶端響應內容
let fileType = mime.getType(filePath);
res.setHeader('Content-Type', `${fileType};charset=UTF-8`);
let rs = this.getStream(filePath);//獲取檔案的可讀流
rs.pipe(res);
}
getStream(filePath) {//返回一個可讀流
return fs.createReadStream(filePath);
}
sendError(req, res, err) {//傳送錯誤
res.statusCode = 500;
res.end(`${err.toString()}`)
}
}
module.exports = Server;
通過以上的程式碼,我們可以看出,我這裡是建立了一個Server類,然後通過在呼叫Server類的start()方法來啟動這樣一個服務,在Server類當中有以下方法:
- start 用來啟動服務的——這個方法裡面主要是通過node的http模組來啟動一個服務,並監聽對應的埠
request 服務監聽函式——這個方法主要是對啟動服務的監聽,具體邏輯這裡還是在程式碼中通過註釋來說明吧:
async request(req, res) {//服務監聽函式 let pathName = url.parse(req.url).path;//獲取到客戶端要訪問的伺服器路徑 let filePath = path.join(this.config.root, pathName);//客戶端要訪問的路徑得到該路徑在伺服器上的對應伺服器物理路徑 if (filePath.indexOf('favicon.ico') > 0) {//這個判斷主要是為了去掉網站預設favicon.ico的請求報錯 this.sendError(req, res, 'not found'); return } try {//在靜態伺服器存在訪問路徑內容 let statObj = await stat(filePath);//通過node來獲取該路徑下的檔案資訊 if (statObj.isDirectory()) {//如果該路徑是對應的資料夾 let directories = await readDir(filePath);//讀取該資料夾裡面的檔案內容,readDir其實是我定義的const readDir = promisify(fs.readdir) let files = directories.map(file => {//這裡主要是為了生成返回html模板內容的對應資料結構如: {title:'顯示的頁面標題',files:[{filename:'1',url:'/1'}]}; return { filename: file, url: path.join(pathName, file) } }); let htmls = this.list({//呼叫模板引擎的渲染方法,這就不對模板引擎做過多說明了,會在最後附上模板引擎的相關連線,這裡用的handlebars title: pathName, files }); res.setHeader('Content-Type', 'text/html');//因為返回的是html頁面,所以需要設定請求頭,告訴客戶端如何來解析 res.end(htmls);//將讀取到的html傳送給客戶端 } else { this.sendContent(req, res, filePath, statObj);//呼叫Server類的sendContent方法,向客戶端傳送內容 } } catch (err) {//靜態伺服器不存在訪問內容 this.sendError(req, res, err);//呼叫Server類的sendError方法,向客戶端傳送錯誤資訊 } }
程式碼的解讀我會根據上一個方法的呼叫來一個個的逐行解讀,那麼接下來時sendContent
- sendContent 向客戶端傳送內容,程式碼段如下:
javascript
sendContent(req, res, filePath, statObj) {//向客戶端響應內容
let fileType = mime.getType(filePath);//這裡是為了實現對MIME型別的支援,所以這裡需要判斷訪問路徑的檔案的MIME型別,主要是通過npm上的mime包來獲取
res.setHeader('Content-Type', `${fileType};charset=UTF-8`);//設定對應MIME的http響應頭,這樣客戶端才能對應的解析
let rs = this.getStream(filePath);//獲取對應路徑檔案的可讀流
rs.pipe(res);//向客戶端傳送內容,這主要是因為res本身就是一個流
}
那麼同樣逐行解讀Server類的getStream方法 - getStream 獲取一個流物件,程式碼如下:
javascript
getStream(filePath) {
return fs.createReadStream(filePath);//返回一個可讀流,供sendContent方法使用
}
那麼以上就已經完成了向客戶端返回對應的訪問路徑資訊了,最後還剩一個Server類的sendError方法,這個方法主要是向客戶端傳送一個錯誤資訊。 - sendError 傳送錯誤資訊,程式碼段如下:
javascript
sendError(req, res, err) {//傳送錯誤
res.statusCode = 500;//設定錯誤碼
res.end(`${err.toString()}`)//向客戶端傳送對應的錯誤資訊字串
}
那麼以上的程式碼就實現了一個這個靜態伺服器的——1.讀取靜態檔案。2.MIME型別支援。這樣兩個功能點,對應的程式碼檔案app.js github地址
功能實現——支援壓縮
因為這個功能點的實現都是基於前面已實現的功能(讀取靜態檔案、MIME型別支援)的基礎上來做的,所以前面那些基礎的就不再做說明,同樣的是先貼上完整程式碼,然後再講壓縮的實現思路、以及壓縮的功能實現的核心程式碼。整體程式碼如下:
```javascript
//新增上檔案壓縮,實現功能有——讀取靜態檔案、MIME型別支援,支援壓縮
const http = require('http')
const path = require('path')
const url = require('url')
const fs = require('fs')
const mime = require('mime')
var zlib = require('zlib');
let chalk = require('chalk');
process.env.DEBUG = 'static:app';
let debug = require('debug')('static:app');//每個debug例項都有一個名字,是否在控制檯列印取決於環境變數中DEBUG的值是否等於static:app
const {promisify} = require('util')
let handlebars = require('handlebars');
const config = require('./config')
const stat = promisify(fs.stat)
const readDir = promisify(fs.readdir)
//獲取編譯模板
function getTemplet() {
let tmpl = fs.readFileSync(path.resolve(__dirname, 'template', 'list.html'), 'utf8');
return handlebars.compile(tmpl);
}
class Server {
constructor(argv) {
this.config = Object.assign({}, config, argv);
this.list = getTemplet()
}
//啟動服務
start() {
let server = http.createServer();
server.on('request', this.request.bind(this))
server.listen(this.config.port);
let url=`http://${this.config.host}:${this.config.port}`;
debug(`靜態服務啟動成功${chalk.green(url)}`);
}
async request(req, res) {//服務監聽函式
let pathName = url.parse(req.url).path;
let filePath = path.join(this.config.root, pathName);
if (filePath.indexOf('favicon.ico') > 0) {
this.sendError(req, res, 'not found',404);
return
}
try {//在靜態服務資料夾存在訪問的路徑內容
let statObj = await stat(filePath);
if (statObj.isDirectory()) {//是資料夾
let directories = await readDir(filePath);
let files = directories.map(file => {
return {
filename: file,
url: path.join(pathName, file)
}
});
let htmls = this.list({
title: pathName,
files
});
res.setHeader('Content-Type', 'text/html');
res.end(htmls);
} else {//是檔案
this.sendContent(req, res, filePath, statObj);
}
} catch (err) {//靜態伺服器不存在訪問內容
this.sendError(req, res, err);
}
}
sendContent(req, res, filePath, statObj) {//向客戶端響應內容
let fileType = mime.getType(filePath);
res.setHeader('Content-Type', `${fileType};charset=UTF-8`);
let enCoding=this.sourceGzip(req,res);
let rs = this.getStream(filePath);//獲取檔案的可讀流
if(enCoding){//開啟壓縮傳輸模式
rs.pipe(enCoding).pipe(res);
}else{
rs.pipe(res);
}
}
sourceGzip(req,res){//資源開啟壓縮傳輸
// Accept-Encoding:gzip, deflate, sdch, br
let encoding=req.headers['accept-encoding'];
if(/\bgzip\b/.test(encoding)){//gzip壓縮格式
res.setHeader('Content-Encoding','gzip');
return zlib.createGzip();
}else if(/\bdeflate\b/.test(encoding)){//deflate壓縮格式
res.setHeader('Content-Encoding','deflate');
return zlib.createDeflate();
}else{
return null;
}
}
getStream(filePath) {//返回一個可讀流
return fs.createReadStream(filePath);
}
sendError(req, res, err,errCode) {//傳送錯誤
if(errCode){
res.statusCode=errCode;
}else{
res.statusCode = 500;
}
res.end(`${err.toString()}`)
}
}
module.exports = Server;
```
通過以上程式碼我們會發現,這裡程式碼只是對像客戶端傳送內容做的sendContent方法做了修改,所以,這裡將會只講sendContent以及sendContent裡面與壓縮相關的sourceGzip方法:
那麼我們一起來看看sendContent和sourceGzip方法吧,程式碼如下:
```javascript
sendContent(req, res, filePath, statObj) {//向客戶端響應內容
let fileType = mime.getType(filePath);
res.setHeader('Content-Type', `${fileType};charset=UTF-8`);
let enCoding=this.sourceGzip(req,res);//呼叫sourceGzip,來實現資源壓縮傳輸
let rs = this.getStream(filePath);//獲取檔案的可讀流
if(enCoding){////如果客戶端支援壓縮格式傳輸,那麼就以壓縮方式傳輸資料
rs.pipe(enCoding).pipe(res);//向客戶端傳送壓縮格式資料
}else{
rs.pipe(res);
}
}
sourceGzip(req,res){//資源開啟壓縮傳輸
// Accept-Encoding:gzip, deflate, sdch, br,客戶端會發送這樣的請求頭,給伺服器判斷
let encoding=req.headers['accept-encoding'];//獲取客戶端傳送的壓縮相關的請求頭資訊,
if(/\bgzip\b/.test(encoding)){//客戶端支援gzip壓縮格式
res.setHeader('Content-Encoding','gzip');//設定請求頭
return zlib.createGzip();//建立並返回一個Gzip流物件
}else if(/\bdeflate\b/.test(encoding)){//客戶端支援deflate壓縮格式
res.setHeader('Content-Encoding','deflate');//設定請求頭
return zlib.createDeflate();//建立並返回一個Deflate流物件
}else{//代表客戶端不支援壓縮格式資料傳輸,
return null;
}
}
```
以上就是對實現資料壓縮傳輸的程式碼實現說明,那麼到這裡,總共就已經實現了三個功能(讀取靜態檔案、MIME型別的支援,支援壓縮),對應的程式碼檔案appGzip.js github地址;
功能實現——斷點續傳(同樣是在appGzip.js的基礎上繼續開發)
因為現在的完整程式碼越來越多了,所以我這裡就不再貼完整的程式碼了,就貼對應功能的核心程式碼吧,最後再附上完整的檔案連結地址。這個功能主要是在獲取檔案流的方法getStream裡面去擴充套件的,斷點續傳的個核心功能如下:
javascript
getStream(req,res,filePath,statObj) {//返回一個可讀流
let start = 0;//可讀流的起司位置
let end = statObj.size - 1;//可讀流的結束位置
let range = req.headers['range'];//獲取客戶端的range請求頭資訊,Server通過請求頭中的Range: bytes=0-xxx來判斷是否是做Range請求
if (range) {//斷點續傳
res.setHeader('Accept-Range', 'bytes');
res.statusCode = 206;//返回指定內容的狀態碼
let result = range.match(/bytes=(\d*)-(\d*)/);//斷點續傳的分段內容
if (result) {
start = isNaN(result[1]) ? start : parseInt(result[1]);
end = isNaN(result[2]) ? end : parseInt(result[2]) - 1;
}
}
return fs.createReadStream(filePath, {//返回一個指定起始位置和結束位置的可讀流
start, end
});
}
那麼上面的程式碼就已經實現了檔案的斷點續傳了,對應完整程式碼檔案github地址;接下來,將繼續實現【支援快取與快取控制】這樣一個功能點;
功能實現——斷點續傳(同樣是在前面所有已完成功能基礎上繼續開發)
之所以要實現快取的支援與控制,主要是為了讓客戶端在訪問服務端時以最小的資料傳輸量得到服務端最新的資源。其實現程式碼如下:
``javascript
${fileType};charset=UTF-8`);
sendContent(req, res, filePath, statObj) {//向客戶端響應內容
if (this.checkCache(req, res, filePath, statObj)) return; //通過sendContent方法實現快取校驗
let fileType = mime.getType(filePath);
res.setHeader('Content-Type',
let enCoding=this.sourceGzip(req,res);
let rs = this.getStream(req,res,filePath,statObj);//獲取檔案的可讀流
if(enCoding){//開啟壓縮傳輸模式
rs.pipe(enCoding).pipe(res);
}else{
rs.pipe(res);
}
}
checkCache(req,res,filePath,statObj){//校驗快取
let ifModifiedSince = req.headers['if-modified-since'];//當資源過期時(使用Cache-Control標識的max-age),發現資源具有Last-Modified宣告,則再次向伺服器請求時帶上頭If-Modified-Since。
let isNoneMatch = req.headers['is-none-match'];//客戶端想判斷快取是否可用可以先獲取快取中文件的ETag,然後通過If-None-Match傳送請求給Web伺服器詢問此快取是否可用。
res.setHeader('Cache-Control', 'private,max-age=10');//Cache-Control private 客戶端可以快取,max-age=10 快取內容將在10秒後失效
res.setHeader('Expires', new Date(Date.now() + 10 * 1000).toGMTString());//伺服器響應訊息頭欄位,在響應http請求時告訴瀏覽器在過期時間前瀏覽器可以直接從瀏覽器快取取資料
let etag = statObj.size;
let lastModified = statObj.ctime.toGMTString();
res.setHeader('ETag', etag);//ETag是實體標籤的縮寫,根據實體內容生成的一段hash字串,可以標識資源的狀態。當資源發生改變時,ETag也隨之發生變化。 ETag是Web服務端產生的,然後發給瀏覽器客戶端。
res.setHeader('Last-Modified', lastModified);//伺服器檔案的最後修改時間
if (isNoneMatch && isNoneMatch != etag) {//快取過期
return false;
}
if (ifModifiedSince && ifModifiedSince != lastModified) {//換存過期
return false;
}
if (isNoneMatch || ifModifiedSince) {//快取有效
res.writeHead(304);
res.end();
return true;
} else {//快取無效
return false;
}
}
“`
那麼以上程式碼就已經把靜態伺服器的【讀取靜態檔案、MIME型別支援、支援壓縮、支援斷點續傳、支援快取與快取控制】這些功能都已經實現了,完整的程式碼檔案GitHub地址,接下來將要實現命令列呼叫我們的靜態檔案伺服器啟用;
功能實現——命令列呼叫
命令列呼叫的功能主要是什麼?
如果沒有命令列呼叫,如果我們想要執行我們這個app.js,那麼就只能是先cmd進入命令列面板,然後在裡面輸入node app.js才能執行app.js。如果我們做了命令列呼叫,那麼我們只需要自定義一個命令假如叫Myserver,這個命令主要功能主要就是執行app.js,那麼我們在cmd命令列裡面就只要輸入Myserver就能實現了,而且還可以通過命令列來實現傳參。例如:我們平時看電腦的ip地址時,我們可以在命令列中輸入ipconfig,就會顯示資訊,也可以通過ipconfig /all 這樣一個命令來顯示完整資訊,那麼後面的這個/all就相當於一個篩選引數了,這樣子就想Linux裡面的命令一樣了,這裡就不再做太多說明了,這裡主要講一下如何將我們的靜態伺服器通過命令列來呼叫;
首先在package.json中提供一個bin欄位,主要是將包裡包含可執行檔案,通過設定這個欄位可以將它們包含到系統的PATH中,這樣直接就可以執行。我這裡新增的bin欄位如下:
javascript
"bin": {
"rcw-staticserver": "bin/app"
}
這裡是主要是將rcw-staticserver這個欄位設定到系統PATH當中去,然後記得一定要執行一次npm link,從而將命令執行內容路徑改到,bin/app檔案來。那麼我這裡就能通過在命令列輸入rcw-staticserver來啟動我的靜態檔案伺服器了。那麼bin資料夾下的app檔案程式碼內容如下:
```javascript
#! /usr/bin/env node //這段程式碼一定要寫在開頭,為了相容各個電腦平臺的差異性
const yargs = require('yargs');//yargs模組,主要是用它提供的argv物件,用來讀取命令列引數
let Server = require('../src/appCache.js');
const child = require('child_process');
const path=require('path')
const os = require('os');
let argv = yargs.option('d', {//通過-d別名或者--root 資料夾名稱來指定對應的靜態檔案伺服器的資料夾目錄
alias: 'root',//指令變數名稱
demand: 'false',//是否必傳欄位
type: 'string',//輸入值型別
default: path.resolve(process.cwd(),'public'),//預設值
description: '靜態檔案根目錄'//欄位描述
}).option('o', {
alias: 'host',
demand: 'false',
default: 'localhost',
type: 'string',
description: '請配置監聽的主機'
}).option('p', {
alias: 'port',
demand: 'false',
type: 'number',
default: 9898,
description: '請配置埠號'
})
.usage('rcw-staticserver [options]')//使用示例
.example(
'rcw-staticserver -d / -p 9898 -o localhost', '在本機的9898埠上監聽客戶端的請求'
).help('h').argv;
let server = new Server(argv).start();//啟動我的靜態檔案伺服器
```
這樣子的話我就能在命令行當中通過輸入rcw-staticserver來直接啟動靜態檔案伺服器了,那麼命令列呼叫的功能也就實現了。
功能實現——程式碼釋出到npm,可通過npm install -g全域性安裝。
這個功能其實相對來說就很簡單了,首先要有個npm官網的賬號,沒有的請自覺註冊吧。命令列裡通過npm login先登入自己的npm賬號,然後再執行npm publish,這個包就很輕鬆的釋出到npm上面去了,也就可以通過npm install -g來進行全域性安裝了。
通過以上的操作我們一個靜態檔案伺服器就已經實現了哦!有不好和錯誤的地方,請大家多多指教。
相關推薦
Node手把手構建一個靜態檔案伺服器
這篇文章主要將會通過node手把手的構建一個靜態檔案伺服器,那麼廢話不多說,開發流程走起來,我們先看一下將要做的這個靜態檔案伺服器將會有哪些功能? 這個靜態檔案伺服器有哪些功能? 讀取靜態檔案 MIME型別支援 支援壓縮 支援斷點續傳 支援快取與快取控制
使用 Azure Blob Stoage 實現一個靜態檔案伺服器
## 什麼是Azure Blob Stoage Azure Blob Stoage 是微軟Azure的物件儲存服務。國內的雲一般叫OSS,是一種用來儲存非結構化資料的服務,比如音訊,視訊,圖片,文字等等。使用者可以通過http在全球任意地方訪問這些資源。這些資源可以公開訪問,也可以私有訪問。看到這些描述立馬就
教你用 100 行 Node.js 程式碼,快速構建一個靜態網站生成器!
近日,我的一位同事向我尋求建議,她打算為自己構建一個部落格。於是,我對靜態網站生成器和部落格引擎進行了一番研究,發現 Hugo 是一個很不錯的選擇。但是,我的同事還有一些特殊要求,比如,她想要一個自定義的部落格網址和 CSS 主題。儘管這些 Hugo 都可以實現,但我並不打算花時間來學習它。我想自己
Nodejs搭建一個的本地靜態檔案伺服器的方法
方法一: 第一步:在Nodejs安裝目錄安裝: npm install connect 第二步:在Nodejs安裝目錄安裝: npm install serve-static 第三步:新建server.js (可以放在專案裡去執行也可以放在Nodejs安裝目錄下執行
原生node寫一個靜態資源伺服器
myanywhere 用原生node做一個簡易閹割版的anywhere靜態資源伺服器,以提升對node與http的理解。 相關知識 es6及es7語法 http的相關網路知識 響應頭 快取相關 壓縮相關 path模組 path.join拼接路徑 path.relative path.basena
使用Nodejs快速搭建一個的本地靜態檔案伺服器
如果我們直接開啟html檔案他是以file:///方式開啟的,但這種方式有時會遇到跨域的問題:“cross-origin”,所以我們需要搭建一個簡易的本地伺服器,Nodejs就可以滿足我們這個需求:比如我的本地伺服器js檔案就是這樣的(我把這個server.js放在了
用原生Node實現一個靜態web伺服器
之前一直用過Apache nginx等靜態web伺服器。 但強大的node.js本身就能作為獨立的web伺服器,不依賴與Apache nginx 下面我們看看怎麼用Node去寫一個靜態伺服器吧 首先,先來看看我的專案結構吧
vue專案或react專案用node搭建靜態檔案伺服器
//npm install express --save-dev 下載express包 //npm install http-proxy-middleware --save-dev 下載代理中介軟體 const fs = require('fs'); const pat
node js構建一個vue並啟動它
ros install 項目 http node js 編譯打包 代碼 -- wid 安裝node js,到運行VUE的簡單過程 1、安裝node js 下載地址:http://nodejs.cn/download/2、安裝完成後運行Node.js command pr
用node.js搭建一個靜態資源站 html,js,css正確加載 跳轉也完美實現!
都在 加載 簡單 pipe tps color exec create 包含 昨天剛買了一個服務器想著用來測試一些自己的項目,由於是第一次建站,在tomcat,linux,node.js間想了好久最終因為node搭建比較方便沒那麽麻煩就決定用node.js來搭建網站項目。
nginx window下的靜態檔案伺服器
nginx.conf檔案 #user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log inf
使用Apache2 搭建靜態檔案伺服器
1.安裝Apache2 sudo apt-get install apache2 2.修改Apache2埠(可以選擇不修改) vi /etc/apache2/ports.conf #將80改為想要的埠 #重啟服務 service apache2 resatrt
Nginx部署vue專案,Nginx搭建一個靜態資源伺服器
一.Nginx安裝(Centos) yum install -y nginx 安裝後啟動nginx service nginx start 通過ip或者域名訪問以下,看看是不是啟動成功了 二.Nginx部署vue 1.vue專案編譯(推薦vue element-
用NodeJS/express-4.0實現的靜態檔案伺服器(serveStatic外掛直接支援HTTP Range請求,因此可用來做mp4流媒體伺服器)
var express = require('express'), serveIndex = require('serve-index'), //只能列表目錄,不能下載檔案? serveStatic = require('serve-stat
nodejs使用nodejs建立簡單的靜態檔案伺服器
在開始之前,應該好好規劃一下專案的檔案目錄了。我的目錄結構如下: assets放置網站的靜態檔案css,js,img等;common存放專案的配置檔案和一些通用檔案;server存放服務處理檔案,將要建立的靜態檔案服務就是放在此目錄中; tpl放置的是模板檔案也就是網頁
Node 搭建簡易 HTTP 靜態資源伺服器
有時候前端開發需要用到伺服器,比如ajax請求之類的,會選擇apache或者nginx或者tomcat,Jboss之類的,現在伺服器太多,但是每次都需要配置環境下載之類的非常麻煩,也許我們只是想預覽一下靜態資源的效果,或者除錯一下簡單的邏輯程式碼而已。 相信現在前端大多數都
NodeJS VS Tomcat搭建高併發靜態檔案伺服器
測試動機 NodeJS因為它的非阻塞I/O和優秀的高併發效能受到越來越多的關注,而且NodeJS的伺服器相對於Nginx其搭建非常簡單,僅需很少的步驟和設定就可以搭建一個高效能的檔案伺服器。之前我有一臺Tomcat伺服器兼做檔案下載的功能,後來我在上面部署了一個NodeJS
基於ES6和原生nodejs實現自定義路由,靜態檔案伺服器和增刪查改的MVC架構分享
基於ES6和原生nodejs來實現一個基於MVC的增刪查改功能示例分享 自定義路由的解耦實現 首先分別處理不同方式的請求: const http = require('http'); const url = require('url')
創業公司如何構建一個分散式檔案儲存系統
有時候初創企業需要快速搭建一個檔案儲存平臺,滿足企業內專案的圖片、視訊、文字等檔案的儲存;並且即使在讀寫檔案的時候,磁碟壞了、伺服器宕機了、交換機壞了、機櫃掉電了甚至機房掛了,使用者還能正常訪問。你同時可能希望公司業務快速增長後,訪問量猛增的時候能夠儘量少的或者不開發程式碼
CMake 構建一個庫檔案,並進行呼叫
一、建立libfile和binfile兩個資料夾。其中libfile為庫檔案,放編譯的庫檔案。binfile檔案放可執行程式和檔案。 二、libfile資料夾結構如下: