{"id":569,"date":"2024-04-29T15:02:36","date_gmt":"2024-04-29T18:02:36","guid":{"rendered":"https:\/\/adrianosantostreina.com.br\/blog\/?p=569"},"modified":"2024-05-06T13:20:54","modified_gmt":"2024-05-06T16:20:54","slug":"como-enviar-e-receber-multiplos-arquivos-em-api-horse","status":"publish","type":"post","link":"https:\/\/adrianosantostreina.com.br\/blog\/como-enviar-e-receber-multiplos-arquivos-em-api-horse\/","title":{"rendered":"Como Enviar e Receber M\u00faltiplos arquivos em API Horse?"},"content":{"rendered":"\n<p>No desenvolvimento moderno de aplica\u00e7\u00f5es web e m\u00f3veis, a habilidade de enviar e receber arquivos atrav\u00e9s de APIs \u00e9 crucial. Em ambientes corporativos, isso permite que sistemas distintos compartilhem documentos, imagens, e outros tipos de arquivos de maneira eficiente. Neste artigo, exploraremos como implementar essa funcionalidade usando a framework Horse no ambiente de programa\u00e7\u00e3o Delphi, focando em endpoints capazes de manusear m\u00faltiplos arquivos simultaneamente.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>Ao desenvolver APIs para o envio e recebimento de arquivos, alguns princ\u00edpios b\u00e1sicos s\u00e3o fundamentais para garantir que o sistema seja seguro, eficiente, flex\u00edvel e f\u00e1cil de usar. Vamos detalhar cada um desses princ\u00edpios:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Seguran\u00e7a<\/h3>\n\n\n\n<p>A seguran\u00e7a \u00e9 a prioridade m\u00e1xima ao permitir o upload de arquivos atrav\u00e9s de uma API. Aqui est\u00e3o algumas medidas de seguran\u00e7a essenciais:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Valida\u00e7\u00e3o de Arquivos<\/strong>: \u00c9 crucial validar os tipos de arquivos recebidos para evitar uploads de arquivos potencialmente perigosos ou n\u00e3o suportados. Isso inclui verificar a extens\u00e3o do arquivo e seu MIME type.<\/li>\n\n\n\n<li><strong>Sanitiza\u00e7\u00e3o de Arquivos<\/strong>: Al\u00e9m da valida\u00e7\u00e3o, os arquivos recebidos devem ser sanitizados para remover qualquer c\u00f3digo malicioso que possa ser executado no servidor ou nos dispositivos dos usu\u00e1rios finais.<\/li>\n\n\n\n<li><strong>Limita\u00e7\u00e3o de Tamanho<\/strong>: Definir um limite m\u00e1ximo para o tamanho dos arquivos recebidos ajuda a prevenir ataques de nega\u00e7\u00e3o de servi\u00e7o (DoS) e a manter o desempenho do sistema.<\/li>\n\n\n\n<li><strong>Controle de Acesso<\/strong>: Implementar autentica\u00e7\u00e3o e autoriza\u00e7\u00e3o para garantir que apenas usu\u00e1rios autorizados possam enviar ou acessar arquivos.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Efici\u00eancia<\/h3>\n\n\n\n<p>Para garantir que o sistema seja capaz de lidar com o envio e recebimento de arquivos sem comprometer o desempenho, considere:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Armazenamento<\/strong>: Escolher uma estrat\u00e9gia de armazenamento adequada, seja em disco, em banco de dados ou servi\u00e7os de armazenamento em nuvem, que possa escalar de acordo com as necessidades.<\/li>\n\n\n\n<li><strong>Gerenciamento de Carga<\/strong>: Implementar t\u00e9cnicas como carregamento ass\u00edncrono e balanceamento de carga para gerenciar eficientemente o tr\u00e1fego pesado e os picos de demanda.<\/li>\n\n\n\n<li><strong>Compress\u00e3o de Arquivos<\/strong>: Aplicar compress\u00e3o de arquivos pode reduzir o uso de banda e melhorar o tempo de transmiss\u00e3o, especialmente para arquivos grandes.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Flexibilidade<\/h3>\n\n\n\n<p>Uma API que lida com arquivos deve ser projetada para ser t\u00e3o flex\u00edvel quanto poss\u00edvel para atender a uma ampla gama de casos de uso:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Suporte a M\u00faltiplos Formatos de Arquivo<\/strong>: Permitir uma variedade de tipos de arquivos, desde documentos de texto e planilhas at\u00e9 imagens e v\u00eddeos.<\/li>\n\n\n\n<li><strong>Configura\u00e7\u00f5es Personaliz\u00e1veis<\/strong>: Permitir que desenvolvedores configurem aspectos como tipos de arquivos permitidos e tamanhos m\u00e1ximos de arquivo atrav\u00e9s de par\u00e2metros de API ou configura\u00e7\u00f5es do servidor.<\/li>\n\n\n\n<li><strong>Adaptabilidade<\/strong>: A API deve ser capaz de se adaptar a diferentes ambientes de infraestrutura ou a mudan\u00e7as nas tecnologias subjacentes sem grandes modifica\u00e7\u00f5es no c\u00f3digo cliente.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Simplicidade<\/h3>\n\n\n\n<p>A simplicidade na interface da API n\u00e3o s\u00f3 facilita a vida dos desenvolvedores, mas tamb\u00e9m reduz a probabilidade de erros:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Documenta\u00e7\u00e3o Clara<\/strong>: Fornecer uma documenta\u00e7\u00e3o compreensiva e exemplos de c\u00f3digo que demonstrem como usar a API para enviar e receber arquivos.<\/li>\n\n\n\n<li><strong>Consist\u00eancia<\/strong>: Manter a API consistente em termos de endpoints, formatos de resposta e manuseio de erros facilita o uso e a integra\u00e7\u00e3o por desenvolvedores.<\/li>\n\n\n\n<li><strong>Ferramentas de Debugging<\/strong>: Oferecer ferramentas ou modos de debugging que possam ajudar os desenvolvedores a testar e resolver problemas relacionados ao envio de arquivos.<\/li>\n<\/ul>\n\n\n\n<p>Adotando esses princ\u00edpios, voc\u00ea pode construir APIs robustas e confi\u00e1veis para o envio e recebimento de arquivos, que ser\u00e3o bem aceitas e amplamente utilizadas pela comunidade de desenvolvedores.<\/p>\n\n\n\n<p>Receber arquivos em um endpoint de uma API \u00e9 uma funcionalidade essencial em muitos sistemas e aplica\u00e7\u00f5es, abrindo a porta para uma s\u00e9rie de opera\u00e7\u00f5es cr\u00edticas que facilitam a intera\u00e7\u00e3o, o processamento e a gest\u00e3o de informa\u00e7\u00f5es. Aqui est\u00e3o algumas raz\u00f5es detalhadas sobre a import\u00e2ncia de ter endpoints que podem receber um ou mais arquivos:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Integra\u00e7\u00e3o de Sistemas<\/h3>\n\n\n\n<p>Em ambientes corporativos, a capacidade de trocar arquivos entre diferentes sistemas automatiza e agiliza processos. Por exemplo, APIs que recebem arquivos podem permitir a integra\u00e7\u00e3o entre um sistema de gest\u00e3o de recursos humanos e plataformas de contabilidade, transferindo dados como folhas de pagamento e relat\u00f3rios de despesas automaticamente.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Processamento e An\u00e1lise de Dados<\/h3>\n\n\n\n<p>Muitas aplica\u00e7\u00f5es dependem da an\u00e1lise de grandes volumes de dados, como imagens, v\u00eddeos, ou documentos textuais. Receber arquivos atrav\u00e9s de APIs permite que esses dados sejam processados e analisados em tempo real ou em lote. Por exemplo, uma aplica\u00e7\u00e3o de sa\u00fade pode receber imagens de radiografias para an\u00e1lise diagn\u00f3stica usando intelig\u00eancia artificial.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Armazenamento e Backup<\/h3>\n\n\n\n<p>APIs que aceitam arquivos podem servir como pontos de entrada para sistemas de armazenamento de dados ou backup. Empresas de todos os tamanhos precisam armazenar documentos importantes de maneira segura e acess\u00edvel, como contratos, registros legais e dados financeiros.<\/p>\n\n\n\n<p>Esses aspectos ilustram como a funcionalidade de receber arquivos em um endpoint \u00e9 crucial para uma ampla gama de aplica\u00e7\u00f5es e ind\u00fastrias, ajudando a melhorar a efici\u00eancia, a seguran\u00e7a, e a colabora\u00e7\u00e3o em processos de neg\u00f3cio essenciais.<\/p>\n\n\n\n<p class=\"has-large-font-size\"><strong>O que \u00e9 Form-Data?<\/strong><\/p>\n\n\n\n<p>O Form-Data \u00e9 um formato utilizado para a transfer\u00eancia de dados entre um cliente (como um navegador ou aplicativo) e um servidor atrav\u00e9s de requisi\u00e7\u00f5es HTTP, especialmente \u00fatil quando se trata do envio de arquivos ou dados. Vamos explorar mais detalhadamente o que \u00e9 Form-Data, como ele funciona e por que \u00e9 amplamente utilizado.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Defini\u00e7\u00e3o e Utiliza\u00e7\u00e3o<\/h3>\n\n\n\n<p>Form-Data \u00e9 um tipo de codifica\u00e7\u00e3o usada em formul\u00e1rios HTML para enviar dados de formul\u00e1rios atrav\u00e9s de requisi\u00e7\u00f5es POST. Este formato \u00e9 particularmente vers\u00e1til porque permite o envio combinado de dados simples (como strings e n\u00fameros) e arquivos. No contexto de APIs, isso \u00e9 extremamente valioso para opera\u00e7\u00f5es que requerem o upload de documentos, imagens, e outros tipos de arquivos, junto com informa\u00e7\u00f5es adicionais como metadados. <\/p>\n\n\n\n<p><em>Imagine enviar o XML da Nota Fiscal para uma API que faz o armazenamento.<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Como funciona o Form-Data?<\/h3>\n\n\n\n<p>Quando um formul\u00e1rio \u00e9 enviado usando o tipo de conte\u00fado <code>multipart\/form-data<\/code>, cada campo do formul\u00e1rio \u00e9 enviado como um &#8220;bloco&#8221; de dados dentro da carga \u00fatil da requisi\u00e7\u00e3o POST, conhecido como &#8220;parte&#8221;. Cada parte cont\u00e9m:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Headers<\/strong>: Cada parte come\u00e7a com um ou mais headers que descrevem o conte\u00fado da parte. Os headers incluem <code>Content-Disposition<\/code> (que inclui o nome do campo e, no caso de arquivos, o nome do arquivo) e <code>Content-Type<\/code> (que especifica o tipo de m\u00eddia do conte\u00fado da parte).<\/li>\n\n\n\n<li><strong>Body<\/strong>: Ap\u00f3s os headers, o corpo da parte cont\u00e9m os dados reais do campo. Para campos de texto, \u00e9 simplesmente o texto; para arquivos, \u00e9 o conte\u00fado bin\u00e1rio do arquivo.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Vantagens do Form-Data<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Flexibilidade<\/strong>: Form-Data pode lidar com v\u00e1rios tipos e formatos de dados simultaneamente, tornando-o ideal para formul\u00e1rios que incluem tanto dados de texto quanto arquivos.<\/li>\n\n\n\n<li><strong>Compatibilidade<\/strong>: \u00c9 amplamente suportado por todas as plataformas e frameworks modernos, facilitando a interoperabilidade entre diferentes tecnologias e linguagens de programa\u00e7\u00e3o.<\/li>\n\n\n\n<li><strong>Efici\u00eancia<\/strong>: Embora n\u00e3o seja o m\u00e9todo mais compacto para enviar dados, sua capacidade de enviar arquivos grandes e dados em uma \u00fanica requisi\u00e7\u00e3o economiza tempo e reduz a complexidade do cliente.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Usos Comuns do Form-Data<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Uploads de Arquivos<\/strong>: Comumente usado para upload de imagens, documentos e outros arquivos em aplica\u00e7\u00f5es web.<\/li>\n\n\n\n<li><strong>Aplica\u00e7\u00f5es Web Interativas<\/strong>: Permite a submiss\u00e3o de formul\u00e1rios complexos que incluem combina\u00e7\u00f5es de texto, sele\u00e7\u00f5es, e uploads de arquivos.<\/li>\n\n\n\n<li><strong>APIs para Manipula\u00e7\u00e3o de M\u00eddia<\/strong>: APIs que aceitam manipula\u00e7\u00e3o de imagens, v\u00eddeos ou outros arquivos de m\u00eddia frequentemente usam Form-Data para receber inputs dos usu\u00e1rios.<\/li>\n<\/ul>\n\n\n\n<p>Em resumo, o Form-Data \u00e9 uma parte integral da web e das APIs modernas, oferecendo uma solu\u00e7\u00e3o robusta e flex\u00edvel para o envio de formul\u00e1rios e arquivos atrav\u00e9s de requisi\u00e7\u00f5es HTTP. \u00c9 uma ferramenta essencial em muitas aplica\u00e7\u00f5es que requerem o envio de informa\u00e7\u00f5es complexas e variadas entre clientes e servidores.<\/p>\n\n\n\n<p class=\"has-large-font-size\"><strong>Como funciona o Form-Data?<\/strong><\/p>\n\n\n\n<p>Quando uma requisi\u00e7\u00e3o \u00e9 feita usando Form-Data, cada campo ou arquivo enviado \u00e9 encapsulado em uma parte separada da mensagem HTTP, com seu pr\u00f3prio cabe\u00e7alho de conte\u00fado. Isso permite que m\u00faltiplos arquivos e campos de dados sejam enviados na mesma requisi\u00e7\u00e3o, facilitando o processamento pelo servidor. Como j\u00e1 foi mencionado anteriormente, ou seja, podemos facilmente receber arquivos e tomar decis\u00f5es sobre o que fazer com eles. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/adrianosantos.link\/treinamentos\" target=\"_blank\" rel=\"noreferrer noopener\"><img fetchpriority=\"high\" decoding=\"async\" width=\"800\" height=\"150\" src=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/02\/Banner-Hotmart-1.png\" alt=\"\" class=\"wp-image-222\" srcset=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/02\/Banner-Hotmart-1.png 800w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/02\/Banner-Hotmart-1-300x56.png 300w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/02\/Banner-Hotmart-1-768x144.png 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/a><\/figure>\n\n\n\n<p class=\"has-large-font-size\"><strong>Como enviar arquivos usando form-data no Postman?<\/strong><\/p>\n\n\n\n<p>Uma boa forma de testar e\/ou entender o mecanismo de envio \u00e9 usar o Postman ou outros aplicativos semelhantes. Para enviar arquivos usando form-data no Postman:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Abra o Postman e crie uma nova requisi\u00e7\u00e3o.<\/li>\n\n\n\n<li>Defina o tipo de m\u00e9todo para POST.<\/li>\n\n\n\n<li>Na aba &#8216;Body&#8217;, selecione a op\u00e7\u00e3o &#8216;form-data&#8217;.<\/li>\n\n\n\n<li>Use os campos para adicionar partes ao form-data. Para arquivos, selecione &#8216;File&#8217; no drop-down de tipo de dados e escolha o arquivo desejado.<\/li>\n\n\n\n<li>Adicione outros campos de dados conforme necess\u00e1rio.<\/li>\n\n\n\n<li>Envie a requisi\u00e7\u00e3o para o servidor.<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"342\" src=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/04\/image-23-1024x342.png\" alt=\"\" class=\"wp-image-580\" srcset=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/04\/image-23-1024x342.png 1024w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/04\/image-23-300x100.png 300w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/04\/image-23-768x257.png 768w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/04\/image-23.png 1125w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Aqui um exemplo simples pra ter uma ideia do que estou falando. No form-data temos as colunas <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Key = Chave da &#8220;parte&#8221; enviada.<\/li>\n\n\n\n<li>File = Arquivo bin\u00e1rio ou texto, define o tipo de conte\u00fado a ser enviado.<\/li>\n\n\n\n<li>Value = O conte\u00fado em propriamente dito.<\/li>\n\n\n\n<li>Content-Type = Tipo de conte\u00fado<\/li>\n\n\n\n<li>Description = Descri\u00e7\u00e3o.<\/li>\n<\/ul>\n\n\n\n<p>Tudo isso pode ser capturado do lado da API para qualquer fim.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Enviando arquivos por Form-Data com Delphi<\/h3>\n\n\n\n<p>Em aplica\u00e7\u00f5es Delphi, a biblioteca Indy \u00e9 frequentemente utilizada para implementar funcionalidades de rede, incluindo o envio de dados via HTTP. Um dos recursos mais \u00fateis da Indy \u00e9 sua capacidade de manejar requisi\u00e7\u00f5es HTTP que incluem o envio de arquivos usando o formato Form-Data. Isso \u00e9 especialmente \u00fatil para desenvolvedores que precisam implementar funcionalidades de upload de arquivos em suas aplica\u00e7\u00f5es cliente.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Componentes Indy para HTTP<\/h4>\n\n\n\n<p>Os componentes principais da Indy que s\u00e3o usados para realizar requisi\u00e7\u00f5es HTTP incluem:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>TIdHTTP<\/strong>: Este componente \u00e9 usado para enviar requisi\u00e7\u00f5es HTTP e receber respostas do servidor. Ele suporta m\u00e9todos HTTP como GET, POST, PUT, entre outros.<\/li>\n\n\n\n<li><strong>TIdMultiPartFormDataStream<\/strong>: \u00c9 utilizado para criar o corpo da requisi\u00e7\u00e3o POST formatada como <code>multipart\/form-data<\/code>, que pode incluir tanto dados textuais quanto arquivos.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Como Funciona o Envio de Arquivos<\/h4>\n\n\n\n<p>O processo de envio de arquivos com Indy em uma aplica\u00e7\u00e3o Delphi envolve a cria\u00e7\u00e3o de uma inst\u00e2ncia do componente <code>TIdHTTP<\/code> e do <code>TIdMultiPartFormDataStream<\/code>. O <code>TIdMultiPartFormDataStream<\/code> permite adicionar partes ao corpo da mensagem, onde cada parte pode representar um campo de dados ou um arquivo. Aqui est\u00e3o os passos b\u00e1sicos:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Cria\u00e7\u00e3o de uma Inst\u00e2ncia de TIdHTTP<\/strong>: O primeiro passo \u00e9 instanciar o componente <code>TIdHTTP<\/code> que ser\u00e1 usado para enviar a requisi\u00e7\u00e3o HTTP.<\/li>\n\n\n\n<li><strong>Configura\u00e7\u00e3o do TIdMultiPartFormDataStream<\/strong>: Em seguida, cria-se uma inst\u00e2ncia de <code>TIdMultiPartFormDataStream<\/code>, onde campos e arquivos s\u00e3o adicionados como partes separadas do formul\u00e1rio.<\/li>\n\n\n\n<li><strong>Adicionar Campos e Arquivos<\/strong>: Para cada campo de dados ou arquivo que precisa ser enviado, adiciona-se uma parte ao <code>TIdMultiPartFormDataStream<\/code>. Para arquivos, especifica-se o caminho do arquivo e o tipo de conte\u00fado (content type).<\/li>\n\n\n\n<li><strong>Enviar a Requisi\u00e7\u00e3o POST<\/strong>: Com o corpo da requisi\u00e7\u00e3o montado, o componente <code>TIdHTTP<\/code> \u00e9 utilizado para enviar uma requisi\u00e7\u00e3o POST ao servidor, passando o <code>TIdMultiPartFormDataStream<\/code> como o corpo da requisi\u00e7\u00e3o.<\/li>\n\n\n\n<li><strong>Tratar a Resposta<\/strong>: Ap\u00f3s enviar a requisi\u00e7\u00e3o, o desenvolvedor pode manipular a resposta do servidor, que pode incluir status de sucesso, mensagens de erro, ou outros dados relevantes.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Vantagens do Uso de Indy para Form-Data<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Simplicidade<\/strong>: A biblioteca Indy simplifica o processo de montagem e envio de requisi\u00e7\u00f5es HTTP complexas.<\/li>\n\n\n\n<li><strong>Flexibilidade<\/strong>: Permite ao desenvolvedor controlar detalhadamente como os dados s\u00e3o enviados, incluindo tipos de conte\u00fado e codifica\u00e7\u00e3o.<\/li>\n\n\n\n<li><strong>Compatibilidade<\/strong>: Como parte do conjunto de ferramentas Delphi, Indy trabalha bem com outras funcionalidades e componentes do Delphi.<\/li>\n<\/ul>\n\n\n\n<p>O uso de Indy para enviar arquivos e dados via Form-Data \u00e9 uma pr\u00e1tica robusta e confi\u00e1vel para desenvolvedores Delphi que trabalham com aplica\u00e7\u00f5es que necessitam de integra\u00e7\u00e3o com servidores web ou APIs que aceitam uploads de arquivos. Essa abordagem aproveita a pot\u00eancia e a flexibilidade do Delphi e da biblioteca Indy para resolver uma necessidade comum em desenvolvimento de software moderno. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/adrianosantos.link\/HorseDocker\" target=\"_blank\" rel=\"noreferrer noopener\"><img decoding=\"async\" width=\"800\" height=\"150\" src=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/03\/Horse-em-Docker-no-Amazon-AWS.png\" alt=\"\" class=\"wp-image-238\" srcset=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/03\/Horse-em-Docker-no-Amazon-AWS.png 800w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/03\/Horse-em-Docker-no-Amazon-AWS-300x56.png 300w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/03\/Horse-em-Docker-no-Amazon-AWS-768x144.png 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/a><\/figure>\n\n\n\n<p class=\"has-large-font-size\"><strong>Criando o exemplo de envio<\/strong><\/p>\n\n\n\n<p>Para o exemplo de envio criei um pequeno exemplo em Firemonkey, voc\u00ea vai perceber que est\u00e1 no formato de aplicativo, mas n\u00e3o se incomode com isso, mesmo em Windows com VCL ou FMX o exemplo funcionar\u00e1 perfeitamente. Desenhe uma tela semelhante a abaixo:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"398\" height=\"598\" src=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/04\/image-22.png\" alt=\"\" class=\"wp-image-573\" srcset=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/04\/image-22.png 398w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/04\/image-22-200x300.png 200w\" sizes=\"(max-width: 398px) 100vw, 398px\" \/><\/figure><\/div>\n\n\n<p>Aqui coloquei um bot\u00e3o para selecionar os arquivos, nesse caso ir\u00e1 abrir um OpenDialog e esses arquivos s\u00e3o carregados em um ListBox ao centro. Um outro bot\u00e3o para envio dos arquivos. O objetivo \u00e9 simples, vamos percorrer o ListBox, e criar uma lista e enviar os arquivos selecionados. Eis o c\u00f3digo do bot\u00e3o selecionar:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \" >procedure TForm1.Button1Click(Sender: TObject);\nbegin\n  SelecionarArquivos;\nend;\n\nprocedure TForm1.SelecionarArquivos;\nvar\n  NomeArquivo: string;\n  i: Integer;\nbegin\n  ListBox1.Items.Clear;\n  if OpenDialog1.Execute then\n  begin\n    for i := 0 to OpenDialog1.Files.Count - 1 do\n    begin\n      NomeArquivo := ExtractFileName(OpenDialog1.Files[i]);\n      ListBox1.Items.Add(OpenDialog1.Files[i]);\n    end;\n  end;\nend;<\/pre><\/div>\n\n\n\n<p>Na verdade publiquei pra voc\u00ea o c\u00f3digo do bot\u00e3o e da fun\u00e7\u00e3o. Criamos uma fu\u00e7\u00e3o chamada <strong>SelecionarArquivos<\/strong> que apenas d\u00e1 um loop no OpenDialog e adiciona os arquivos no ListBox. Bem simples. <\/p>\n\n\n\n<p>O envio para a API \u00e9 relativamente simples, d\u00e1 um pouco de trabalho, mas n\u00e3o \u00e9 nenhum bicho de 7 cabe\u00e7as. Veja o c\u00f3digo a baixo e a explica\u00e7\u00e3o:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \" >procedure TForm1.Button3Click(Sender: TObject);\nvar\n  HTTP: TIdHTTP;\n  FormData: TIdMultiPartFormDataStream;\n  i: Integer;\nbegin\n  HTTP := TIdHTTP.Create(nil);\n  FormData := TIdMultiPartFormDataStream.Create;\n  try\n    for i := 0 to ListBox1.Count - 1 do\n    begin\n      FormData.AddFile('arquivos', ListBox1.Items[i], 'multipart\/form-data');\n    end;\n\n    \/\/ Tente enviar os arquivos para a API\n    try\n      HTTP.Post('http:\/\/localhost:9000\/upload', FormData);\n      if HTTP.ResponseCode =  200 then\n        ShowMessage(HTTP.ResponseText);\n    except\n      on E: Exception do\n        ShowMessage('Erro ao enviar arquivos: ' + E.Message);\n    end;\n\n  finally\n    FormData.Free;\n    HTTP.Free;\n  end;\nend;<\/pre><\/div>\n\n\n\n<p>Basicamente o que fazemos \u00e9 instanciar um idHTTP e um TIdMultiPartFormDataStream para enviarmos. Percorremos o ListBox em um loop e adicionamos os arquivos \u00e0 vari\u00e1vel do tipo TIdMultiPartFormDataStream (FormData). Usamos o m\u00e9todo AddFile. Em seguida chamamos o m\u00e9todo Post do HTTP e enviamos o FormData para a api. Aqui estamos simulando uma api rodando no endere\u00e7o <code>http:\/\/localhost:9000\/uload<\/code>.<\/p>\n\n\n\n<p>Um detalhe importante, na linha onde adicionamos o arquivo:<\/p>\n\n\n\n<p><code>FormData.AddFile('arquivos', ListBox1.Items[i], 'multipart\/form-data');<\/code><\/p>\n\n\n\n<p>Perceba que podemos adicionar um nome para a Key (primeiro par\u00e2metro). O segundo par\u00e2metro \u00e9 o pr\u00f3prio arquivo e o terceiro o seu <strong>content-type<\/strong>. E n\u00e3o esque\u00e7a de declarar as units <code>IdHTTP <\/code>e <code>IdMultipartFormData<\/code> ao uses do formul\u00e1rio.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Recebendo Arquivos em uma API Horse no Delphi<\/h3>\n\n\n\n<p>Quando se trata de construir APIs robustas em Delphi, a framework Horse \u00e9 uma excelente escolha para lidar com requisi\u00e7\u00f5es HTTP de maneira simples e eficaz. Um dos casos de uso comuns \u00e9 a configura\u00e7\u00e3o de endpoints para receber arquivos. Neste caso, vamos explorar como configurar um endpoint chamado <code>upload<\/code> para receber arquivos atrav\u00e9s de uma requisi\u00e7\u00e3o POST ou PUT.<\/p>\n\n\n\n<p>Voc\u00ea pode construir seu endpoint onde desejar, no exemplo abaixo criei essei endpoint em uma classe TControllerArquivos. <\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Na minha classe TControllerArquivos estou usando o middleware Swagger que j\u00e1 registra a rota automaticamente e cria as vari\u00e1veis globais <strong>FRequest<\/strong> e <strong>FResponse <\/strong>em substitui\u00e7\u00e3o ao <strong>Req<\/strong> e <strong>Res<\/strong> padr\u00e3o do Horse, portato atente-se a esse detalhe e modifique.<\/p>\n<\/blockquote>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \" >procedure TControllerArquivos.DoArquivos;\nvar\n  I: Integer;\n  lResult: string;\n  lStream: TMemoryStream;\n  Diretorio: string;\n  LBody: TJSONObject;\n\nbegin\n  Diretorio := 'C:\\APP_HOMO\\Imagens';\n  ForceDirectories(Diretorio);\n\n  lResult := '';\n  for I := 0 to Pred(FRequest.RawWebRequest.Files.Count) do\n  begin\n     var x := FRequest.RawWebRequest.Files[I];\n     lResult := lResult + ' - ' + FRequest.RawWebRequest.Files[I].FileName;\n     lStream := TMemorySTream.Create;\n     try\n       lStream.LoadFromStream(FRequest.RawWebRequest.Files[I].Stream);\n       lStream.Position := 0;\n       lStream.SaveToFile(TPath.Combine(Diretorio, FRequest.RawWebRequest.Files[I].FileName));\n     finally\n       lStream.Free;\n     end;\n  end;\n\n  FResponse.Send('Arquivos carregados com sucesso!');\nend;<\/pre><\/div>\n\n\n\n<p>O que eu quero que voc\u00ea observe nesse cen\u00e1rio? Estou simulando que os arquivos ser\u00e3o armazenados em uma pasta que defini em uma vari\u00e1vel logo no in\u00edcio do c\u00f3digo. Em seguida vem o &#8220;<em>pulo do gato&#8221;<\/em>, a gente d\u00e1 um loop em <code>RawWebRequest.Files<\/code> da vari\u00e1vel <code>FRequest <\/code>(ou Req) e carregamos arquivo por arquivo em um TMemoryStream para em seguida salvar na pasta desejada. Isso poderia inclusive ser feito para salvar em uma tabela do banco de dados. <\/p>\n\n\n\n<p>\u00c9 poss\u00edvel codificar de forma diferente recebendo apenas um \u00fanico arquivo, a codifica\u00e7\u00e3o \u00e9 ainda mais simples, mas preferi deixar arqui esse m\u00e9todo que atende um ou mais arquivos e tamb\u00e9m \u00e9 bem f\u00e1cil de entender. <\/p>\n\n\n\n<p>O que achou? Deixe seu feedback nos coment\u00e1rios. \ud83d\ude09<\/p>\n\n\n\n<p><strong>Agradecimentos<\/strong><\/p>\n\n\n\n<p>Cr\u00e9ditos existem para serem dados, portanto meus agradecimentos aos colegas <strong>Vinicius Sanchez<\/strong> e <strong>Alexandre Magno<\/strong> que apoiaram enviaram algumas dicas para concluir o artigo.<\/p>\n\n\n\n<p>Comunidade no <a href=\"https:\/\/t.me\/AdrianoSantosCommunity\">Telegram<\/a><\/p>\n\n\n\n<p>\ud83d\ude80Comente no campo abaixo \ud83d\udc47\ud83d\udc47\ud83d\udc47 o que achou e qual sua d\u00favida.<\/p>\n\n\n\n<p>Te vejo na pr\u00f3xima<\/p>\n\n\n\n<p>Adriano Santos<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>No desenvolvimento moderno de aplica\u00e7\u00f5es web e m\u00f3veis, a habilidade de enviar e receber arquivos atrav\u00e9s de APIs \u00e9 crucial. Em ambientes corporativos, isso permite que sistemas distintos compartilhem documentos, imagens, e outros tipos de arquivos de maneira eficiente. Neste artigo, exploraremos como implementar essa funcionalidade usando a framework Horse no ambiente de programa\u00e7\u00e3o Delphi, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":582,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[24,1],"tags":[20,59,58,57,21,60],"class_list":["post-569","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-api","category-blog","tag-api","tag-arquivos","tag-files","tag-form-data","tag-horse","tag-upload"],"_links":{"self":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/569","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/comments?post=569"}],"version-history":[{"count":8,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/569\/revisions"}],"predecessor-version":[{"id":581,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/569\/revisions\/581"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/media\/582"}],"wp:attachment":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/media?parent=569"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/categories?post=569"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/tags?post=569"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}