Olá pessoal, hoje eu vou falar um pouco de como trabalhar com foto e Web Api com a linguagem C# para web ou desktop. O primeiro ponto que gostaria de informar é que a melhor performance para desenvolver um aplicativo ou sistema que tenha foto é com esses dois próximos passos importantes.

Primeiro passo

Definir um servidor onde as fotos vão ficar. Isso porque é necessário deixar a foto em um servidor disponível para todos verem, porém não são todos que vão ver. Isso significa que nem todos os usuários podem acessar as fotos no servidor, só aquele que for dono da foto.

Existem vários servidores para hospedagem de fotos hoje em dia, alguns deles inclusive te fornece um endereço para fazer upload e download. Outros fornecem apenas API para que você desenvolva um sistema consumindo a API disponibilizada.

O que eu mais utilizo hoje em dia é o AWS da Amazon e o Azure da Microsoft. Existe também o Cloudinary e muitos outros [1]. Ainda dentro do primeiro passo, é importante você definir o banco de dados que irá utilizar.

Segundo passo

Dentro do segundo passo, é importante definir em seu sistema quem vai fazer o upload da imagem que no meu ponto de vista, se for um sistema web ele vai fazer antes de mandar para o banco de dados, se for mobile, ele que deve fazer o upload antes de mandar para o banco de dados.

Depois de fazer o upload da imagem, deve ser pego o nome da imagem gerada aleatoriamente e enviada para o Web API feito para gravar os dados do banco de dados. Mas apenas o nome da imagem ou então o endereço dela. O endereço completo por exemplo: https://endereco_do_site/pasta/imagem_29293.png.

Com o nome e endereço da imagem, ai sim é hora de gravar a imagem dentro do banco de dados. O sistema depois precisa renderizar o endereço como imagem passando o endereço completo. Para alguns casos, é melhor colocar apenas o nome da imagem dentro do banco de dados, isso porque caso o cliente mude de servidor, basta mudar a base da URL que tudo volta a funcionar mostrando a imagem.

Em diversas empresas que trabalhei, o erro estava:

  1. A imagem armazenada direta no banco de dados, deixa o banco lento para mostrá-la;
  2. O nome da imagem armazenada direta no banco de dados com o endereço completo do servidor, isso faz com que, depois do servidor cheio, é necessário armazenada em outro local, mas manter as imagens antigas no antigo servidor. O que fazer? É necessário ter uma tabela no banco de dados informando os endereços dos servidores, assim a tabela pode pegar de um endereço ou de outro;
  3. Outro erro comum é ter a imagem fixa no código ou o endereço do servidor fixo no código sem qualquer tipo de comentário ou então com uma classe sem constantes.

Eu prefiro fazer da seguinte forma:

  1. Gerar o banco de dados para armazenar o nome da imagem;
  2. Gerar uma tabela apenas com o endereço do servidor ou servidores;
  3. Ao gravar o nome da imagem no banco, indicar como chave secundária qual o endereço do servidor pela tabela com endereços dos servidores.
  4. Deixar a parte web ou mobile fazer o upload da imagem dentro do servidor;
  5. Existem códigos prontos em PHP que basta chamar passando o endereço do arquivo para fazer upload da imagem pelo mobile com a imagem de forma binária.

Código Web API

Aqui eu vou mostrar como funciona o código de Web API feito na linguagem C# e usando a ferramenta Visual Studio da Microsoft.

Código 1.1 - Consultar usando rota com o id do aluno.

    [Route("api/Foto/Aluno/{IdAluno}")]
    [ResponseType(typeof(FotoTDB))]
    public IEnumerable<FotoTDB> GetFotoByAluno(Int32 idAluno)
    {
        StringBuilder str = new StringBuilder();
        str.Append(@"SELECT
                        IdFoto, IdTipoFoto, IdAluno, NomeFoto
                    FROM
                        FotoTDB
                    WHERE IdAluno = @IdAluno");

        IDataParameter idStudent = new SqlParameter();
        idStudent.DbType = DbType.String;
        idStudent.ParameterName = "@IdAluno";
        idStudent.Value = idAluno;
        idStudent.SourceColumn = "IdAluno";

        var resultado = db.Database.SqlQuery<FotoTDB>(str.ToString(),
            idStudent).AsEnumerable();

        if (resultado == null)
            return null;

        return resultado;
    }

O código 1.1 mostra primeiro a rota criada e que também necessita que seja passado o Id do Aluno, note que o parâmetro que ele precisa receber é o mesmo que está no método, isto é, o mesmo nome digitado na rota é o mesmo que recebe como parâmetro.

Logo depois, faço um SELECT com os campos da tabela de banco de dados e com a condição WHERE passando o IdAluno como parâmetro. Em seguida, utilizei o IDataParameter para definir o parâmetro com o valor recebido. Para finalizar, utilizei o SqlQuery para executar os valores e retornar todos os campos do SELECT.

O código 1.2 mostra como fazer o POST dos dados, isto é, o INSERT de valores dentro do banco de dados através de uma classe e utilizando um envio mais seguro do que o GET.

Código 1.2 - Fazendo Post dos dados

	// POST: api/Foto
    [ResponseType(typeof(FotoTDB))]
    public IHttpActionResult PostFotoTDB(FotoTDB fotoTDB)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        db.FotoTDB.Add(fotoTDB);
        db.SaveChanges();

        return CreatedAtRoute("DefaultApi", new { id = fotoTDB.idFoto }, fotoTDB);
    }

Note que o código 1.2 não tem uma rota criada por mim utilizando a tag ROUTE como mostrado no código 1.1. Isso porque o método é feito via POST e recebe como parâmetro uma classe toda de dados chamada FotoTDB. Os dados são verificados se são válidos e se forem, é feito um Add com a classe toda.

Para finalizar, basta salvar as mudanças usando o método do EntityFramework chamado SaveChanges(). No final do método, basta criar uma nova rota passando o valor do id da foto criada.

Já o código 1.3 mostra como deletar do banco de dados um dado importante pelo Id. Para isso basta fazer um GET normal.

Código 1.3 - Deletando a foto do banco de dados

	// DELETE: api/Foto/5
    [ResponseType(typeof(FotoTDB))]
    public IHttpActionResult DeleteFotoTDB(long id)
    {
        FotoTDB fotoTDB = db.FotoTDB.Find(id);
        if (fotoTDB == null)
        {
            return NotFound();
        }

        db.FotoTDB.Remove(fotoTDB);
        db.SaveChanges();

        return Ok(fotoTDB);
    }

No meu ponto de vista, todo e qualquer tipo de informação hoje em dia não precisa ser deletada, basta desativar. Se você é o dono do banco de dados, quanto mais informação nele, melhor é para o seu negócio.

Para este caso eu mudaria o método de Remove para Update e SaveChanges() mudando apenas um status de ativo para inativo. Mesmo assim, o id da foto é passada pelo método como recebimento de parâmetro e depois disso é verificado se existe esse id no banco de dados, se existir, então os dados serão removidos.

No final do método, o MVC retorna um valor de Ok com a classe de fotoTDB todo preenchido.

O código 1.4 mostra como é feito a atualização dentro da API mudando apenas um status.

Código 1.4 - Atualizando os dados dentro do banco de dados.

	// PUT: api/Foto/5
    [ResponseType(typeof(void))]
    public IHttpActionResult PutFotoTDB(long id, FotoTDB fotoTDB)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        if (id != fotoTDB.idFoto)
        {
            return BadRequest();
        }

        db.Entry(fotoTDB).State = EntityState.Modified;

        try
        {
            db.SaveChanges();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!FotoTDBExists(id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return StatusCode(HttpStatusCode.NoContent);
    }

Note que o nome do método do código 1.4 começa com a palavra Put, isso significa que o método é responsável por atualizar as informações do banco de dados. O nome do método já diz muita coisa.

O primeiro passo que o método faz é verificar se os dados enviados são válidos, se forem então continua, senão, retorna um BadRequest. Depois é verificado se o id da foto foi enviado como parâmetro separado, note que o esse método recebe dois tipos de parâmetros. O primeiro é o id e o segundo é a classe preenchida com todos os novos valores.

Com os dados em perfeita situação, o State da classe é modificada com o parâmetro EntityState.Modified. Dentro do bloco try os dados do banco são salvos com o comando SaveChanges(). Em caso de erro, existe o bloco catch que pode pegar o erro usando o comando DbUpdateConcurrencyException.

No final do método existe o StatusCode retornado para o programa que chamou.

Caso você queira saber mais e entender mais como funciona o EntityFramework e o Web API, acesse a referência [2] para maiores informações. Espero que tenha gostado e qualquer dúvida, pode entrar em contato pelo site www.mauriciojunior.org.

Referências

[1] - Hospedagem de imagens gratuitamente, Autor PHILIPE KLING DAVID, Data de criação: 10 DE JUNHO DE 2008, Data de acesso: 19 de Dezembro de 2017.

[2] - Entity Framework e Web API - Criando e consumindo Web API, Autor Mauricio Junior, Data de acesso: 20 de Dezembro de 2017.