ホームページ  >  記事  >  ウェブフロントエンド  >  Nodeで静的ファイルを提供する

Nodeで静的ファイルを提供する

不言
不言オリジナル
2018-07-07 17:18:211205ブラウズ

この記事では、静的ファイル サービスを提供するための Node の使用方法を主に紹介します。これには、必要な友達が参考にできるように共有します。 、JavaScript、画像など)サービスが必要になることがよくあります。この記事では、静的ファイルサーバーを自作する方法を紹介します。

静的ファイル サーバーを作成する

各静的ファイル サーバーには、ファイル サービスを提供する基本ディレクトリである ルート ディレクトリ があります。したがって、これから作成するサーバー上で、静的ファイル サーバーのルート ディレクトリとして機能するルート変数を定義する必要があります。

var http = require('http')
var join = require('path').join
var fs = require('fs')

var root = __dirname

__dirname は Node の魔法の変数であり、その値はディレクトリへのパスです。ファイルが置かれている場所。この例では、サーバーは、このスクリプトが配置されているディレクトリを静的ファイルのルート ディレクトリとして使用します。

ファイルのパスとともに、ファイルのコンテンツも転送する必要があります。 根目录,也就是提供文件服务的基础目录。所以我们要在即将创建的服务器上定义一个root变量,它将作为我们这个静态文件服务器的根目录:

var server = http.createServer(function(req, res){
  let path = join(root, req.url)
  let stream = fs.createReadStream(path)
  stream.on('data', function(chunk){
    res.write(chunk)
  })
  stream.on('end', function(){
    res.end()
  })
})

server.listen(3000)

__dirname 在Node中是一个神奇的变量,它的值是该文件所在目录的路径。在本例中,服务器会将这个脚本所在的目录作为静态文件的根目录。

有了文件的路径,还需要传输文件的内容。
这可以用fs.ReadStream完成,它是Node中Stream类之一。成功调用 fs.createReadStream() 会返回一个新的 fs.ReadStream 对象。
下面的代码实现了一个简单但功能完备的文件服务器。

var server = http.createServer(function(req, res){
  let path = join(root, req.url)
  let stream = fs.createReadStream(path)
  stream.pipe(res)
})

server.listen(3000)

这个文件服务器大体能用,但还有很多细节需要考虑。接下来我们要优化数据的传输,同时也精简一下服务器的代码。

用STREAM.PIPE()优化数据传输

虽然上面的代码看上去还不错,但Node还提供了更高级的实现机制:Stream.pipe()。用这个方法可以极大简化服务器的代码。 优化后代码如下:

ReadableStream.pipe(WritableStream)

这种写法,是不是更简单,更清晰了呢?

理解流和管道

流是Node中很重要的一个概念,你可以把Node中的管道想象成水管,如果你想让某个源头(比如热水器)流出来的水流到一个目的地(比如厨房的水龙头),可以在中间加一个管道把它们连起来,这样水就会顺着管道从源头流到目的地。
Node中的管道也是这样,但其中流动的不是水,而是来自源头(即ReadableStream)的数据,管道可以让它们“流动”到某个目的地(即WritableStream)。你可以用pipe方法把管道连起来:

let readStream = fs.createReadStream('./original.txt') 
let writeStream = fs.createWriteStream('./copy.txt') 
readStream.pipe(writeStream)

读取一个文件(ReadableStream)并把其中的内容写到另一个文件中(WritableStream)用的就是管道:

req.pipe(fs.createWriteStream('./req-body.txt'))

所有ReadableStream都能接入任何一个WritableStream。比如HTTP请求(req)对
象就是ReadableStream,你可以让其中的内容流动到文件中:

  stream.on('error', function(err){
    res.statusCode = 500
    res.end('服务器内部错误')
  })

运行

现在我们来运行上面的代码,我们在根目录下放一张图片,比如peiqi.jpg。
在浏览器中输入http://127.0.0.1:3000/peiqi.jpg,发现可爱的peiqi已经出现在你的面前了。peiqi.jpg被当作响应主体从http服务器送到了客户端(浏览器)。
Nodeで静的ファイルを提供する

虽然已经品尝到了成功的滋味,但这个静态文件服务器还不够完整,因为它很容易出错。想象一下,如果用户不小心输入了一个并不存在的资源,比如abc.html,服务器就会马上崩掉。所以我们还得给这个文件服务器加上错误处理机制,让它足够健壮

处理服务器错误

在Node中,所有继承了EventEmitter的类都可能会发出error事件。为了监听错误,在fs.ReadStream上注册一个error事件处理器(比如下面这段代码),返回响应状态码500表明有服务器内部错误:

var server = http.createServer(function(req, res){
  let path = join(root, req.url)

  fs.stat(path, function(err, stat) {
    if (err) {
      if ('ENOENT' == err.code) {
        res.statusCode = 404
        res.end('Not Found')
      } else {
        res.statusCode = 500
        res.end('服务器内部错误')
      }
    } else { // 有该文件
      res.setHeader('Content-Length', stat.size)
      var stream = fs.createReadStream(path)
      stream.pipe(res)

      stream.on('error', function(err) { // 如果读取文件出错
        res.statusCode = 500
        res.end('服务器内部错误')
      })
    }
  })
})

server.listen(3000)

用fs.stat()实现错误处理

我们可以用fs.stat()来获取文件的相关信息,如果文件不存在,fs.stat()会在err.code中放入ENOENTこれは、Node.js の Stream クラスの 1 つである fs.ReadStream を使用して実行できます。 fs.createReadStream() の呼び出しが成功すると、新しい fs.ReadStream オブジェクトが返されます。
以下のコードは、シンプルだが完全に機能するファイル サーバーを実装します。

rrreee

このファイル サーバーは通常は機能しますが、詳細については考慮すべき点がたくさんあります。次に、データ送信を最適化し、サーバー コードを合理化する必要があります。

STREAM.PIPE() を使用してデータ送信を最適化する

上記のコードは適切に見えますが、Node はより高度な実装メカニズム Stream.pipe() も提供します。この方法を使用すると、サーバー コードを大幅に簡素化できます。 最適化されたコードは次のとおりです:

rrreee

この書き方の方がシンプルでわかりやすいでしょうか?

ストリームとパイプについて

ストリームは Node において非常に重要な概念です。特定の供給源 (給湯器など) からの水を必要とする場合、Node のパイプを水道管と考えることができます。 to flow 途中にパイプを追加して目的地(キッチンの蛇口など)を接続し、水源から目的地までパイプに沿って水が流れます。

ノード内のパイプにも同じことが当てはまりますが、パイプ内を流れるのは水ではなく、ソースからのデータです (つまり、ReadableStream)。パイプはパイプを特定の宛先に「流す」ことができます。つまり、 WritableStream)。パイプ メソッドを使用してパイプを接続できます:

rrreee

パイプを使用してファイル (ReadableStream) を読み取り、その内容を別のファイル (WritableStream) に書き込みます:

rrreee

すべての ReadableStream は、任意の 1 つの WritableStream に接続できます。たとえば、HTTP リクエスト (req) オブジェクトは ReadableStream であり、コンテンツをファイルにフローさせることができます。

rrreeeRun
次に、上記のコードを実行しましょう。 peiqi などのルート ディレクトリに画像を置きます。 jpg .

ブラウザに http://127.0.0.1:3000/peiqi.jpg と入力すると、かわいい peiqi が目の前に現れます。 peiqi.jpg は、応答本文として http サーバーからクライアント (ブラウザー) に送信されます。 🎜Nodeで静的ファイルを提供する🎜🎜この静的ファイル サーバーは成功を収めていますが、エラーが発生しやすいため、十分に完成していません。ユーザーが abc.html などの存在しないリソースを誤って入力した場合、サーバーが即座にクラッシュすることを想像してください。したがって、このファイル サーバーにエラー処理メカニズムを追加して、ファイル サーバーを十分に堅牢にする必要があります。 🎜🎜サーバーエラーの処理🎜🎜 Node では、EventEmitter を継承するすべてのクラスがエラー イベントを発行する可能性があります。エラーを監視するには、fs.ReadStream にエラー イベント ハンドラーを登録し (次のコードなど)、応答ステータス コード 500 を返して内部サーバー エラーを示します: 🎜rrreee🎜 fs.stat() を使用してエラー処理を実装します🎜 🎜 fs.stat() を使用してファイル関連の情報を取得できます。ファイルが存在しない場合、fs.stat() は err.code に ENOENT を挿入します。応答が返された後、エラー コード 404 を返して、ファイルが見つからなかったことをクライアントに示すことができます。 fs.stat() が他のエラー コードを返す場合は、一般的なエラー コード 500 を返すことができます。 🎜リファクタリングされたコードは次のとおりです: 🎜rrreee🎜注意🎜🎜このセクションで構築されるファイル サーバーは簡易バージョンです。これを運用環境に導入する場合は、入力の有効性をより徹底的にチェックして、ユーザーが意図しないディレクトリ トラバーサル攻撃によってコンテンツの一部にアクセスすることを防ぐ必要があります。 🎜🎜まとめ🎜🎜 これを読んだ後は、あなたは賢明で、Node を使用して静的サーバーを作成する方法をマスターしていると思います。次の記事では、Node を使用してユーザーがアップロードしたファイルを処理し、保存する方法を紹介します。サーバー内で。 🎜🎜上記がこの記事の全内容です。その他の関連コンテンツについては、PHP 中国語 Web サイトをご覧ください。 🎜🎜関連する推奨事項: 🎜🎜🎜Node を使用してファイルのアップロードを処理する🎜🎜🎜

ES6 の書き込みを通じて Redux ソースコードの一部を解釈します

以上がNodeで静的ファイルを提供するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。