Publicado em 13/01/2020

Upload de imagem para o Azure Storage com Node

Upload de imagem para o Azure Storage com C#

No artigo passado comentei sobre os motivos para se fazer upload de imagem para o Azure, bem como uma implementação da mesma utilizando C#. Neste artigo vou abordar o envio de imagens para o Azure Storage novamente, porém utilizando JavaScript (Node).

IMPORTANTE: Não utilize este tutorial para envio de imagens direto do Frontend, ou seja, não deixe nada disso no seu App Angular, React, Vue ou o quer que seja, mantenha isto no Backend. O motivo deste cuidado é que precisaremos da Connection String para nosso Storage e deixar isto no Front é tornar fácil o acesso a esta informação.

Iniciando o projeto

Para este exemplo, estou usando uma API básica criada com o Express, se quiser, pode iniciar seu projeto com este comando:

npm install –g express-generator  
express minhaapi –no-view  
cd minhaapi  
npm install  

Isto vai gerar um projeto apenas API, em adicional, vamos criar um controlador (controllers/controller.js) com o seguinte método:

exports.uploadImage = async (req, res, next) => {
    // TODO
}

Para finalizar vamos para o arquivo de rotas (routes/index.js) e criar uma nova rota para o método POST apontando para o controlador que criamos:

var express = require('express');
var router = express.Router();
const controller = require('../controllers/controller');

/* GET home page. */
router.get('/', function (req, res, next) {
    res.render('index', {
        title: 'Express'
    });
});

router.post('/', controller.uploadImage);

module.exports = router;

Instalando os pacotes

Para este caso, vamos utilizar uma lib do Azure (Sim, tem pronto) para facilitar. O time do Azure disponibiliza pacotes para diferentes linguagens, se engana quem acha que é apenas para .NET.

Neste caso vamos utilizar o pacote chamado azure-storage, que pode ser instalado pelo seguinte comando:

npm install azure-storage –save  

Isto é tudo que precisamos do Azure para fazer upload das nossas imagens.

Em adicional, para gerar nomes aleatórios eu uso sempre o GUID, e tem um pacote que recomendo que é o UUID:

npm install uuid –save

Referenciando os Pacotes

O primeiro passo é importar os módulos do Azure e UUID que vamos precisar para trabalhar, e insto é feito no topo do nosso controlador, desta forma:

const uuid = require('uuid/v1');
const azure = require('azure-storage');

exports.uploadImage = async (req, res, next) => {
    // TODO
}

Acessando o Blob Storage

A primeira coisa que precisamos para enviar um arquivo para o Azure e a referência de um Blob/Container, e para isto precisamos antes de uma chave de acesso que pode ser obtida no portal do Azure na opção Azure Storage > Seu Storage > Access Keys.

Com a chave em mãos, vamos criar o objeto de refência que vai permitir a transferência da imagem:

const uuid = require('uuid/v1');
const azure = require('azure-storage');

exports.uploadImage = async (req, res, next) => {
    const blobSvc = azure.createBlobService("SEU ACCESS KEY");
}

Preparando o arquivo

Nossa imagem chegará no formato Base64 e este será divido em duas partes, sendo a primeira o tipo da imagem e a segunda a imagem em si.

Além disso precisamos gerar um nome único para esta imagem para não ter problemas de conflito. Desta forma nosso código fica assim:

const uuid = require('uuid/v1');
const azure = require('azure-storage');

exports.uploadImage = async (req, res, next) => {
    const blobSvc = azure.createBlobService("SEU ACCESS KEY");

    // Gera um nome único para o arquivo
    let filename = uuid().toString() + '.jpg';

    // Obtem a imagem em base64 do corpo da requisição
    let rawdata = req.body.image;

    // Separa a hash recebida em duas partes
    let matches = rawdata.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/);

    // Obtém o tipo da imagem
    let type = matches[1];

    // Obtém a imagem em si
    let buffer = new Buffer(matches[2], 'base64');
}

Salvando a Imagem

Com tudo pronto, podemos usar o método CreateBlockBlobFromText do pacote do Azure Storage para fazer upload de uma imagem no formato Base64 para o servidor.

Neste caso estou utilizando Async/Await (Não esqueça do Try/Catch) para aguardar a execução do método, e caso algo dê errado, eu simplesmente defino o nome do arquivo como padrão.

Isto é apenas para o exemplo e precisa ser melhorado no seu código, OK?

const uuid = require('uuid/v1');
const azure = require('azure-storage');

exports.uploadImage = async (req, res, next) => {
    const blobSvc = azure.createBlobService("SEU ACCESS KEY");

    // Gera um nome único para o arquivo
    let filename = uuid().toString() + '.jpg';

    // Obtem a imagem em base64 do corpo da requisição
    let rawdata = req.body.image;

    // Separa a hash recebida em duas partes
    let matches = rawdata.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/);

    // Obtém o tipo da imagem
    let type = matches[1];

    // Obtém a imagem em sí
    let buffer = new Buffer(matches[2], 'base64');

    // Salva a imagem
    await blobSvc.createBlockBlobFromText('SEUCONTAINER', filename, buffer, {
        contentType: type
    }, function (error, result, response) {
        if (error) {
            filename = 'default.png'
        }
    });
}

Retornando a URL da imagem

Se tudo deu certo, basta retornarmos a URL da imagem na resposta, como mostrado abaixo, que também demonstra nossa versão final do controlador.

const uuid = require('uuid/v1');
const azure = require('azure-storage');

exports.uploadImage = async (req, res, next) => {
    const blobSvc = azure.createBlobService("SEU ACCESS KEY");

    // Gera um nome único para o arquivo
    let filename = uuid().toString() + '.jpg';

    // Obtem a imagem em base64 do corpo da requisição
    let rawdata = req.body.image;

    // Separa a hash recebida em duas partes
    let matches = rawdata.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/);

    // Obtém o tipo da imagem
    let type = matches[1];

    // Obtém a imagem em sí
    let buffer = new Buffer(matches[2], 'base64');

    // Salva a imagem
    await blobSvc.createBlockBlobFromText('SEUCONTAINER', filename, buffer, {
        contentType: type
    }, function (error, result, response) {
        if (error) {
            filename = 'default.png'
        }
    });

    const fileUrl = `https://SEUSTORAGE.blob.core.windows.net/SEUCONTAINER/${filename}`;
    return res.status(200).json({
        url: fileUrl
    });
}


Compartilhe este artigo


André Baltieri

7x Microsoft MVP

Olá eu sou o André Baltieri, desenvolvedor Web desde 2003, já trabalhei no Brasil e nos EUA, em projetos de diversos tamanhos.

Recebi por sete vezes consecutivas, o prêmio de Most Valuable Professional da Microsoft, um reconhecimento global dado para os maiores influentes em suas tecnologias.

Atuei também como Head of People, recrutando, selecionando e direcionando a carreira de mais de 70 desenvolvedores em uma das melhores empresas para se trabalhar do Brasil.

Sou palestrante em diversos eventos como ASP.NET Conference, DevXperience, TDC, GDG dentre outros e desde 2012 realizo treinamentos e consultorias em diversas empresas do Brasil, acumulando uma ótima experiência que também transformo em cursos InCompany e Online.



Cursos Relacionados



Carreiras Relacionadas