Catalog · How the catalog works
horse-multipart
Middleware nativo de alto desempenho para parsing e tratamento de requisições multipart/form-data (upload de arquivos e formulários) no framework Horse.
- ★ 4 on GitHub
Anyone may press Interesting, signed in or not. It helps others find this project.
README
horse-multipart
Middleware nativo de alto desempenho para parsing e processamento de requisições multipart/form-data (upload de arquivos e campos de formulário) no framework Horse.
Ele intercepta requisições contendo fluxos de múltiplos arquivos e campos de texto comum, processa os dados diretamente na memória utilizando ponteiros binários de alta velocidade, persiste os arquivos temporariamente em disco e injeta as referências e metadados no corpo da requisição (Req.Body).
⚙️ Instalação
A instalação deve ser feita utilizando o gerenciador de pacotes boss:
boss install horse-multipart⚡️ Ciclo de Vida & Gerenciamento de Memória
- Fase Recomendada: Registro no início das configurações das rotas (
preParsing/ antes do roteamento). - Limpeza Automática (Zero Memory Leak): Quando a requisição termina, o Horse destrói automaticamente o objeto
THorseMultipartinjetado noReq.Body. O destructor deTHorseMultipartlimpa a lista de arquivos (THorseMultipartFile), os quais excluem fisicamente os arquivos temporários do disco caso eles não tenham sido salvos ou movidos pelo desenvolvedor usando o métodoSaveToFile.
🛠️ Configuração Avançada
É possível customizar o diretório de upload dos arquivos temporários e o limite de tamanho individual de cada arquivo usando a classe fluida TMultipartConfig:
uses
Horse,
Horse.Multipart;
begin
// Configuração customizada
THorse.Use(Multipart(
TMultipartConfig.New
.UploadDir('C:\meus_uploads_temporarios') // Diretório temporário customizado
.MaxFileSize(10 * 1024 * 1024) // Limite de 10 MB por arquivo
));
// ... suas rotas
end.Se nenhum parâmetro for informado, o middleware usará o diretório temporário padrão do sistema operacional (ex: %TEMP% no Windows) e não limitará o tamanho dos arquivos.
📖 Exemplo Prático
Abaixo, um exemplo completo demonstrando como recuperar campos normais do formulário e salvar arquivos enviados via multipart/form-data.
Exemplo 1: Utilizando Req.Body (Método Recomendado)
uses
System.SysUtils,
Horse,
Horse.Multipart;
begin
THorse.Use(Multipart());
THorse.Post('/upload',
procedure(Req: THorseRequest; Res: THorseResponse)
var
LMultipart: THorseMultipart;
LFile: THorseMultipartFile;
LNomeUsuario: string;
begin
// Obtém o container multipart processado do Body
LMultipart := Req.Body<THorseMultipart>;
if not Assigned(LMultipart) then
begin
Res.Send('Requisição inválida ou sem dados multipart').Status(400);
Exit;
end;
// 1. Obtendo campos de texto comuns do formulário
LNomeUsuario := LMultipart.GetFieldValue('nome', 'Usuário Anônimo');
// 2. Obtendo o arquivo pelo nome do campo (input name)
LFile := LMultipart.GetFileByFieldName('foto');
if Assigned(LFile) then
begin
// Salva o arquivo em seu destino final
// Nota: O arquivo temporário será movido fisicamente, liberando o espaço temporário.
LFile.SaveToFile('C:\uploads\' + LFile.FileName);
Res.Send(Format('Olá %s, arquivo "%s" (%d bytes) recebido com sucesso!', [
LNomeUsuario, LFile.FileName, LFile.Size
])).Status(200);
end
else
begin
Res.Send('Nenhum arquivo enviado sob o campo "foto"').Status(400);
end;
end);
THorse.Listen(9000);
end.Exemplo 2: Utilizando Injeção de Dependência (Req.Services)
Para projetos que utilizam o container de injeção de dependência (Services) do Horse, o middleware injeta dinamicamente as instâncias de THorseMultipart e do primeiro arquivo temporário recebido via RTTI:
uses
Horse,
Horse.Multipart;
begin
THorse.Use(Multipart());
THorse.Post('/upload-di',
procedure(Req: THorseRequest; Res: THorseResponse)
var
LMultipart: THorseMultipart;
LFile: THorseMultipartFile;
begin
// Resolve as dependências injetadas pelo middleware no request
LMultipart := Req.Services.Resolve<THorseMultipart>;
LFile := Req.Services.Resolve<THorseMultipartFile>;
LFile.SaveToFile('C:\uploads\' + LFile.FileName);
Res.Send('OK').Status(200);
end);
THorse.Listen(9000);
end.🗂️ Estrutura de Métodos e Propriedades
THorseMultipart
Fields: TDictionary<string, string>: Dicionário bruto contendo todos os campos de texto chave/valor.Files: TObjectList<THorseMultipartFile>: Lista de arquivos recebidos no upload.GetFieldValue(const AFieldName: string; const ADefault: string = ''): string: Obtém o valor de um campo de texto de forma segura, retornando um valor padrão caso ele não exista.GetFileByFieldName(const AFieldName: string): THorseMultipartFile: Retorna a referência do arquivo associado ao nome do campo enviado pelo formulário.
THorseMultipartFile
FieldName: string: Nome do campo de formulário associado (ex:foto).FileName: string: Nome real do arquivo enviado pelo cliente (ex:foto_perfil.png).ContentType: string: MIME type do arquivo (ex:image/png).Size: Int64: Tamanho do arquivo em bytes.TempFileName: string: Caminho físico completo para o arquivo temporário no disco.SaveToFile(const APath: string): Move o arquivo temporário com segurança e de forma atômica para o caminho final informado, criando diretórios intermediários automaticamente caso não existam.
🚀 Arquitetura & Performance
- Processamento Seguro de Fluxo Binário: O parser lê o stream de entrada diretamente através de buffers binários na memória (
TMemoryStream.Memory), localizando delimiters de partes via varredura por ponteiros de byte (PByte). - Baixo Consumo de Memória: Apenas os metadados e cabeçalhos permanecem em memória. O conteúdo binário de arquivos é gravado de forma imediata em disco, evitando exaustão de memória sob uploads volumosos.
- Totalmente Standalone: Zero dependência de bibliotecas visuais ou componentes pesados como
VclouFMX, tornando o middleware 100% compatível com aplicações de console e serviços Windows/Linux (via compilador Delphi e Free Pascal).
📄 Licença
Este projeto está licenciado sob a Apache License 2.0.

