Atualizado: 21/06/2025

Este conteúdo é original e não foi gerado por inteligência artificial.

Enviando Arquivos em Node.js

O envio de arquivos estáticos é uma tarefa bastante comum para uma aplicação web. Vamos analisar como enviar arquivos em uma aplicação Node.js.

Suponha que temos três arquivos no diretório do projeto:

  • app.js
  • about.html
  • index.html

O arquivo app.js é o arquivo principal da aplicação. No arquivo index.html, definimos o seguinte código:

<!DOCTYPE html>
<html>
  <head>
    <title>Principal</title>
    <meta charset="utf-8" />
  </head>
  <body>
    <h1>Principal</h1>
  </body>
</html>

De forma semelhante, definimos o código no arquivo about.html:

<!DOCTYPE html>
<html>
  <head>
    <title>Sobre</title>
    <meta charset="utf-8" />
  </head>
  <body>
    <h1>Sobre</h1>
  </body>
</html>

Nossa tarefa será enviar o conteúdo desses arquivos para o usuário.

Primeiro Método

Para ler um arquivo, podemos usar o método fs.createReadStream(), que lê o arquivo em um fluxo. Em seguida, com o método pipe(), podemos ligar os arquivos lidos ao fluxo de gravação, ou seja, ao objeto response. Então, colocamos no arquivo app.js o seguinte código:

const http = require("http");
const fs = require("fs");

http
  .createServer(function (request, response) {
    console.log(`Endereço solicitado: ${request.url}`);
    // obtém o caminho após a barra
    const filePath = request.url.substring(1);
    // verifica se o arquivo existe
    fs.access(filePath, fs.constants.R_OK, (err) => {
      // se ocorrer um erro, envia o código de status 404
      if (err) {
        response.statusCode = 404;
        response.end("Recurso não encontrado!");
      } else {
        fs.createReadStream(filePath).pipe(response);
      }
    });
  })
  .listen(3000, function () {
    console.log("Servidor iniciado na porta 3000");
  });

Primeiramente, obtemos o endereço solicitado. Suponha que o endereço solicitado corresponda diretamente ao caminho do arquivo no servidor. Em seguida, com a função assíncrona fs.access, verificamos a disponibilidade do arquivo para leitura. O primeiro parâmetro da função é o caminho do arquivo. O segundo parâmetro é uma opção que define o tipo de verificação de acesso. Nesse caso, o valor fs.constants.R_OK indica que estamos verificando os direitos de leitura do arquivo. O terceiro parâmetro é uma função de callback que recebe um objeto de erro. Se ocorrer um erro (o arquivo não está disponível para leitura ou não foi encontrado), enviamos o código de status 404.

Para enviar o arquivo, aplicamos a cadeia de métodos:

fs.createReadStream(filePath).pipe(response);

O método fs.createReadStream(filePath) cria um fluxo de leitura, um objeto fs.ReadStream. Para obter os dados do fluxo, chamamos o método pipe(), que recebe um objeto da interface stream.Writable ou um fluxo de gravação. Esse é exatamente o caso do objeto http.ServerResponse, que implementa essa interface.

Vamos iniciar a aplicação e acessar no navegador o endereço http://localhost:3000/index.html:

index.html em Node.js

De forma semelhante, podemos acessar o endereço http://localhost:3000/about.html:

about.html em Node.js

Nesse caso, enviamos arquivos HTML, mas de maneira similar podemos enviar diferentes tipos de arquivos. Por exemplo, definimos no projeto a pasta public e nela criamos um novo arquivo styles.css com o seguinte conteúdo:

body {
  font-family: Verdana;
  color: navy;
}

Aplicamos esses estilos na página index.html:

<!DOCTYPE html>
<html>
  <head>
    <title>Principal</title>
    <meta charset="utf-8" />
    <link href="public/styles.css" rel="stylesheet" type="text/css" />
  </head>
  <body>
    <h1>Principal</h1>
  </body>
</html>

E então acessamos index.html:

Arquivos estáticos em Node.js

Segundo Método

O segundo método envolve a leitura dos dados usando a função fs.readFile() e o envio com o método response.end():

const http = require("http");
const fs = require("fs");

http
  .createServer(function (request, response) {
    console.log(`Endereço solicitado: ${request.url}`);
    // obtém o caminho após a barra
    const filePath = request.url.substring(1);
    fs.readFile(filePath, function (error, data) {
      if (error) {
        response.statusCode = 404;
        response.end("Recurso não encontrado!");
      } else {
        response.end(data);
      }
    });
  })
  .listen(3000, function () {
    console.log("Servidor iniciado na porta 3000");
  });

O resultado será similar, porém existem algumas diferenças:

fs.createReadStream

  • Fluxo de Dados (Streaming): fs.createReadStream cria um fluxo de leitura para o arquivo, permitindo que ele seja lido em partes (chunks) e transmitido diretamente para o cliente. Isso é útil para arquivos grandes, pois não há necessidade de carregar o arquivo inteiro na memória antes de enviá-lo.
  • Uso de Memória: Como os dados são lidos e enviados em partes, o uso de memória é mais eficiente, o que é ideal para servidores que lidam com muitos usuários ou arquivos grandes.
  • Desempenho: A leitura em fluxo pode ser mais rápida para grandes arquivos, pois começa a enviar os dados imediatamente, sem esperar que todo o arquivo seja lido.

fs.readFile

  • Leitura Completa: fs.readFile lê o arquivo inteiro na memória antes de enviar os dados para o cliente. Isso pode ser mais simples de implementar para arquivos pequenos, mas se torna ineficiente para arquivos grandes.
  • Uso de Memória: Requer que o arquivo inteiro seja carregado na memória. Para arquivos grandes ou em sistemas com recursos limitados, isso pode levar a problemas de memória.
  • Desempenho: Pode ser mais lento para arquivos grandes, pois precisa ler todo o arquivo antes de começar a enviá-lo. No entanto, para arquivos pequenos, a diferença de desempenho pode ser insignificante.
Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com