Processamento de Imagem ReactJS - NodeJS

Dia bom.

Passo as perguntas no Reactjs (lado do cliente) e Nodejs (lado do servidor).

Recentemente, em meu pequeno projeto, surgiu a questão de quão fácil e simples é possível trocar imagens do tipo cliente-servidor.

Hoje vamos aprender como enviar dados binários (especificamente imagens) do lado do cliente e processá-los no servidor. Bem-vindo ao gato.

Se o seu aplicativo da Web for uma rede social ou messenger ou algo semelhante, certamente você terá que trabalhar com dados binários, na maioria dos casos, é o processamento de imagens. Isso será discutido.

Para ter uma idéia geral, eu a interpretarei sequencialmente.

Dê uma olhada no seguinte


  1. Sistema de números binários e sistema de números decimais
  2. Página de código : ASCII , Unicode
  3. Bit e byte
  4. Formato hexadecimal
  5. Arquivo binário
  6. Threads de buffer e nodejs
  7. ArrayBuffer e Uint8Array
  8. Filereader

Sistema de números binários e sistema de números decimais.


Este é um número escrito usando dois caracteres: uns e zeros.
Em termos simples, é 2 (base) a potência de n (o número de dígitos); por exemplo, o número 10001 possui 5 dígitos:

4 dígitos = 1; 2 ^ 4 = 16;
3 dígitos = 0;
2 dígitos = 0;
1 dígito = 0;
0 dígito = 1; 2 ^ 0 = 1;

1 verdadeiro - faça um cálculo;
0-falso - não calcula;

Como resultado, obtemos 16 + 1 = 17;
Com a operação reversa, o computador apresenta os dados em formato binário.

const num = 17; //  
const binNum = num.toString(2); //    
const initNum = parseInt(binNum, 2); //  

O sistema de números decimais é um número escrito com 10 caracteres, de 0 a 9. Nós os usamos todos os dias.

O fato é que um computador vive de acordo com a apresentação de informações. Se escrevermos em nossa língua nativa ou contamos em decimal, para um computador tudo isso é uma representação binária. Você pergunta: “O que significa representação binária?”. Como meu professor de inglês disse, "como você ouve, está escrito". O computador apresenta arquivos que contêm texto ou outros, ou quaisquer cálculos no sistema de números binários - essa é a representação binária. O idioma da máquina, o número "17" é - 10001.

Página de código: ASCII, Unicode


Surge a questão. É claro com números, mas e o texto? Como a máquina converterá texto em binário? Tudo é simples. Para isso, existem codificações como ASCII ou Unicode. Esta é uma tabela simples ( página de códigos ), na qual existe um mapeamento para o número de nossos caracteres, por exemplo, o caractere "S" é o número 53 de acordo com a tabela ASCII, o computador apresentará o número 53 em formato binário - 110101.
No que diz respeito ao Unicode, esse é um padrão poderoso que inclui Codificação UTF-8, que é muito procurada em sistemas de espaço na web e em sistemas unix. O princípio de operação é geral.

Bit e byte


Um bit é uma unidade de medida de informação por um computador. E já sabemos como um computador representa informações. Sim! Você está certo. Um bit é 1 ou 0. Para um computador, 1 ou 0 é algo como um transistor, verdadeiro ou falso. Agora não é nada difícil entender o que é um byte - são 8 bits, também é chamado de octeto (do tipo consiste em 8).

Formato hexadecimal


Passamos para o formato "hexadecimal". Falamos sobre o sistema numérico binário, o sistema decimal, entre outras coisas, existe um sistema numérico hexadecimal, os tipógrafos entenderão o que quero dizer. Este é um número escrito com 16 caracteres, de 0 a 9 e de af. Surge a pergunta: "Por que é tão complicado?". Como a unidade de memória é um byte de 8 bits, é mais conveniente escrever seu valor em dois dígitos hexadecimais. Além disso, no padrão Unicode, o número do caractere geralmente é escrito em formato hexadecimal usando pelo menos 4 dígitos.
Esse formato funciona da seguinte maneira: no caso de um byte de 8 bits, ele divide 8 bits por gênero, ou seja, 10101011 - 1010 | 1011, depois converte cada parte em conformidade. 1010-a, 1011-b;

const num = 196; //  
const hexNum = num.toString(16); //   hex 
const initNum = parseInt(hexNum, 16); //     -  

Arquivo binário


Passamos para o próximo item, que também é chamado de arquivo binário - é uma matriz de bytes. Por que é binário? Os bytes consistem em bits, ou seja, caracteres de um sistema de números binários; portanto, o nome é binário. Absolutamente todos os arquivos se encaixam na categoria de arquivo binário, ou seja, arquivos contendo texto, imagens - todos esses são arquivos binários, portanto, dados binários, portanto, dados binários.

Frequentemente, os dados binários são gerados pelos caracteres da página de código ASCII, bem como no formato hexadecimal, em imagens específicas. Vou dar um exemplo. Temos a seguinte imagem:

Assista anexo


Sua visualização parcial é representada como hex-agent-smith

Assista anexo

ASCII, hex , .

ArrayBuffer e Uint8Array


ArrayBuffer - objeto para trabalhar com dados binários em javascript. Corrige o comprimento da memória para trabalhar com o binário. Por exemplo: new ArrayBuffer (256) - cria um objeto semelhante a uma matriz com um tamanho de 256 bytes, nem mais - nem menos. Cada byte possui informações específicas. ArrayBuffer não é uma matriz e os métodos da matriz não são aplicáveis ​​a ela. Você faz uma pergunta, como usá-lo? Um objeto Uint8Array fornece uma representação ArrayBuffer em um número de 8 bits não assinado, ou seja, de 0 a 255.

Filereader


FileReader ? Este é o construtor para criar o seguinte:

<input type="file">

Qual é o próximo?


Agora considere um ótimo exemplo que demonstra o processamento de imagens:

  1. Módulo ReactJS
    import React, {useState, useRef, useCallback} from 'react';
    import axios from 'axios';
    
    export const UPLOAD_AVATAR = 'http://localhost:8080/api/upload_avatar';
    
    function App() {
      //   ref   FileReader
      const fileRef = useRef(null);
      const [ loading, setLoading ] = useState(false);
    
      const handleSubmit = useCallback( event => {
        event.preventDefault();
    
        const fetchData = async (uint8Array) => {
          try {
            const response = await axios({
              method: 'post',
              url: UPLOAD_AVATAR,
              data: [...uint8Array] //    JSON,   
            });
    
            setLoading(false);
            console.log(response);
          } catch (e) {
            console.error(e.message, 'function handleSubmit')
          }
        };
    
        if(!fileRef.current) return void null;
    
        const reader = new FileReader();
        reader.onloadend = () => {
          const uint8Array = new Uint8Array(reader.result);
          setLoading(true);
          fetchData(uint8Array);
        };
    
    
        //  
        reader.readAsArrayBuffer(fileRef.current[0]);
    
        //  reader.readAsBinaryString(fileRef.current[0]) 
        //  MDN,
        //      File API specification, 
        //    
        //  ,     
        //  readAsArrayBuffer
        // https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsBinaryString
      }, []);
    
      const nodeDom = (
        <form onSubmit={handleSubmit}>
          <div>
            <input
              onChange={e => fileRef.current = e.target.files}
              accept="image/*"
              type="file"
              id="button-file"
            />
          </div>
          <button type="submit">{loading ? '...' : ''}</button>
        </form>
      );
    
      return nodeDom
    }
    
    export default App;
    
                   

  2. Módulo ExpressJS
    const express = require("express");
    const cors = require("cors");
    
    const crypto = require('crypto');
    const fs = require('fs');
    
    const PORT = 8080;
    
    const app = express();
    
    app.use(express.static("public"));
    app.use(express.json({ limit: "50mb" }));
    app.use(cors());
    
    app.post("/api/upload_avatar", (req, res) => {
      console.log(req.body);
      const randomString = crypto.randomBytes(5).toString('hex');
      const stream = fs.createWriteStream(`./public/images/${randomString}.png`);
    
      stream.on('finish', function () {
        console.log('file has been written');
        res.end('file has been written');
      });
    
      stream.write(Buffer.from(req.body), 'utf-8');
      stream.end();
    });
    
    app.listen(PORT, () => console.log(`Server running at ${PORT}`));
    
                  


Total:


  • Por que precisamos de codificações
  • Visão geral de dados binários
  • Maneira recomendada de enviar bytes
  • Objeto de buffer
  • Objeto FileReader
  • Implementação simples em ganchos

All Articles