Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Duvida sobre o envio de todo o cadastro de alunos

Esses módulos do WebService me interessam demais poque estou terminando um aplicativo de logística onde o funcionamento de gravação final é muito parecido com o o cadastro de alunos que estamos utilizando nas aulas. Mas minha maior dúvida/preocupação é que não vi nada nos módulos das aulas que trate o envio da foto do aluno para o servidor e preciso demais dessa informação. Minha aplicação deverá enviar uma imagem da assinatura do cliente para o meu server que, após tratar todas as informações, gerará um pdf para enviar por email ao cliente e aprender sobre o envio da foto do aluno é muito importante para mim. Isso será abordado??? Pergunto porque dei "uma avançada" nos módulos e não encontrei em nenhuma parte a abordagem sobre esse procedimento. Obrigado!

7 respostas

Oi Arildo, tudo bem?

Para enviar arquivos (fotos) para uma web api, primeiro ela precisa ter um endpoint configurado para receber o arquivo. Então vai depender do ambiente do seu servidor, qual linguagem ou framework está sendo utilizado.

A requisição pode ser feita a partir de algumas configuração do Retrofit utilizando requisições HTTP Multipart, neste tópico do StackOverflow tem alguns exemplos de código que fazem isso.

[]s

Boa tarde Alex!

Tudo bem sim graças a Deus e espero que com você e todos os seus também.

Nosso webservice foi feito em PHP utilizando o SLIM FRAMEWORK.

Na verdade nós estamos "apanhando" bastante dele...rs...uma vez que é o primeiro webservice que criamos para uso com um app próprio que estamos colocando no ar em nossa empresa, ainda teremos que desenvolver outro para controle de nossos técnicos de campo que hoje é utilizado um app terceirizado mas que deixa um pouco a desejar já que não é específico para nossa empresa.

O app que fizemos agora e só está aguardando funcionar o envio de arquivos é para controle de logística onde, ao final do atendimento, o cliente irá "assinar" na tela do app que, quando clicado no botão de encerramento do atendimento o arquivo gerado da assinatura deverá seguir para o nosso provedor para que possamos armazenar o resultado do atendimento em formato .PDF em nosso banco ORACLE que temos em nossa estrutura interna.

Todo app já está funcionando, falta apenas o envio do arquivo e espero poder contar com sua orientação para conseguir "essa proeza"...rs...

Vou já mexer no app com base na informação do StackOverflow que passou e se puder me dar uma luz de como "receber" o arquivo te agradeço muito.

Obrigado!

Na parte de download de arquivos, você pode usar o Retrofit também, para isso eu sugiro a leitura deste artigo que mostra todos os exemplos. Observe que tem o jeito para arquivos pequenos e outro para arquivos maiores utilizando o @Streaming.

Boa tarde Alex!

Com base no que me passou eu consegui fazer e enviar o arquivo tão logo ele seja capturado está funcionando. Só que para fazer a sincronia eu preciso pegar o arquivo da pasta onde ele está para enviar quando não estiver sincronizado, ou seja, montei um sincronizado das imagens conforme fizemos nas aulas. O problema é que aí ele envia para o meu servidor, mas não o arquivo exatamente. Ele envia como sendo o nome do arquivo correto, mas o conteúdo é outro, na verdade é a string do caminho e nome dele onde se encontra no celular. Tenho certeza que é algo que comi bola, mas não estou conseguindo encontrar e queria ver contigo se pode me ajudar nesse quesito.

Esse é o código do sincronizador das imagens

    public void Sinc_Ger() {
        Roteiro_Dao dao = new Roteiro_Dao(context);
        List<Img_mod> imgs = dao.Lista_Img_NS();
        dao.close();

        if (imgs.size() > 0) {
            for (Img_mod img : imgs) {

                Img_Sinc(img.getPasta(), img.getArquivo());

            }
        }

O conteúdo do img.getPasta() é: /storage/emulated/0/Inprint/Logistica/Imagens/34032_1_1.jpg

Já o conteúdo do img.getArquivo() é: 34032_1_1.jpg

Quando ele chega no servidor para mim, ele chega como 34032_1_1.jpg corretamente, mas de 63 bytes, então eu o renomeei para um arquivo .txt e o conteúdo dele era exatamente o conteúdo do getPasta()...rs...

Ou seja, ele enviou o caminho dentro do arquivo e não estou conseguindo encontrar onde estou errando.

O código do Img_Sinc() é esse:

public void Img_Sinc(String caminho, String corpo) {

        File file = new File(String.valueOf(caminho));

        RequestBody requestFile = RequestBody.create(MediaType.parse(String.valueOf(file)), caminho);
        RequestBody descBody = RequestBody.create(MediaType.parse("text/plain"), corpo);

        Call call = new Retro_Img().getImg_Service().Upl_Img(requestFile, descBody);

        //Finalizando a call de envio do arquivo de imagem
        call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                Log.i("Assinatura: ", "Assinatura enviada com Sucesso!");
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                Log.e("Assinatura Falha: ", t.getMessage());
            }
        });
    }

Se eu usar esse código na Activity que tira a foto, tudo bem, ele sobe a imagem corretamente.

Fui então coloca-lo numa outra classe para poder fazer a sincronia e aí ele funciona com esse erro que comentei, de o conteúdo do arquivo que sobe é na verdade um texto com o caminho onde a imagem está armazenada no celular.

O Retro_Img é o seguinte:

public class Retro_Img {
    private final Retrofit retrofit;
    public Retro_Img() {

        //Criando o interceptador de log das requisições
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        //Criando o client que irá interceptar os logs do Retrofit
        OkHttpClient.Builder client = new OkHttpClient.Builder();
        client.addInterceptor(interceptor);

        retrofit = new Retrofit.Builder().baseUrl("http://brasilscan.com.br/teste/")
                .addConverterFactory(JacksonConverterFactory.create())
                .client(client.build())
                .build();
    }

    public Img_Service getImg_Service() { return retrofit.create(Img_Service.class); }

O service é o seguinte:

public interface Img_Service {
    //Método para inclusão de um novo atendimento (Att1)
    @POST("img_add")
    Call<Void> Ins_Img(@Body Img_mod img);

    //Método para excluir um Atendimento buscando pelo nome fantasia (Att1)
    @DELETE("img_del/{fantasia}")
    Call<Void> Del_Img(@Path("fantasia") String fantasia);


    //Definindo o caminho para entregar o arquivo enviado
    String BASE_URL = "http://www.brasilscan.com.br/teste/";

    /*
    //Definição da chamada com dois parâmetros, nome do arquivo e descrição
    @Multipart
    @POST("Api.php?apicall=upload")
    Call<MyResponse> uploadImage(@Part("image\"; filename=\"myfile.jpg\" ") RequestBody file, @Part("desc") RequestBody desc);
    */

    //Definição da chamada com dois parâmetros, nome do arquivo e descrição
    @Multipart
    @POST("Api.php?apicall=upload")
    Call<Void> Upl_Img(@Part("image\"; filename=\"myfile.jpg\" ") RequestBody file, @Part("desc") RequestBody desc);
}

O código do PHP eu não coloquei porque é exatamente o que estava no tutorial que me enviou, inclusive, como eu disse, ele está funcionando corretamente quando é para trabalhar com uma imagem recem capturada, agora o problema é que para funcionar na sincronia que estou "queimando pestana" por aqui.

solução!

Encontrado o problema!

Era o tamanho do arquivo e algumas parametrizações da classe.

Opa Arildo, fico contente que tenha encontrado a solução, essas semanas estão bem corridas pra mim e só consegui tempo para ver o tópico agora e notei que conseguiu resolver.

Um detalhe importante é que os nomes dos métodos devem seguir o padrão camelCase, então ao invés de Upl_Img, pode colocar como uplImg, porém, veja que abreviando pode ficar ruim para a leitura, então o ideal seria algo como uploadImage(). Isso serve para todo o código

[]s