Uploads
Validação e armazenamento de arquivos enviados pela classe Upload.
Construir e processar
Framework\Support\Upload recebe o array de arquivo e oferece configuração fluente por MIME, extensão, tamanho máximo, diretório, nome aleatório, prefixo e entidade/ID. Presets forImages($maxMb,$entity,$entityId=null) e forDocuments($maxMb, $entity, $entityId = null) apoiam políticas comuns; process() valida e move o arquivo.
$upload = (new Upload($_FILES['avatar'] ?? []))
->forImages(3, 'users', $userId)
->setRandomName(true);
if (!$upload->process()) {
$errors = $upload->getErrors();
} else {
$filename = $upload->getFilename();
}
API de resultado
getFilename(), getErrors(), hasErrors(), getFirstError(). Upload::resolvePath($entity,$filename,$entityId=null) retorna o caminho relativo entity[/id]/filename sob o armazenamento; helper uploadUrl() forma a URL correspondente.
Práticas seguras
- Validar extensão e MIME real; limitar tamanho.
- Não confiar em nome fornecido pelo browser; nomes aleatórios reduzem colisões/exposição.
- Guardar apenas o nome/caminho relativo no banco e construir URL por helper.
- Evitar armazenar uploads executáveis dentro do document root.
O código usa Fileinfo para identificar MIME e armazenamento sob storage/; verifique permissões do processo PHP.
Fluxo de formulário a storage
Cenário: atualizar avatar do usuário autenticado. O formulário precisa de multipart/form-data; obtenha o array `$_FILES` (ou Request::file()), configure a política e só persista o nome depois que process() retornar true.
$upload = (new \Framework\Support\Upload($_FILES['avatar'] ?? []))
->forImages(3, 'users', $this->userId());
if (!$upload->process()) {
$message = $upload->getFirstError();
// Preserve o avatar atual; não atualize o Model.
} else {
$filename = $upload->getFilename();
// Armazene apenas esse nome no campo avatar.
}`forImages($maxMb,$entity,$entityId=null)` e `forDocuments($maxMb,$entity,$entityId=null)` exigem tamanho máximo e entity. O nome é aleatório por padrão; `setRandomName()` existe, mas não é preciso chamá-lo para o padrão seguro. process() retorna bool; filename só é preenchido em sucesso.
| Preset | MIME/extensões permitidos | Parâmetros |
|---|---|---|
| forImages | JPEG/JPG, PNG, GIF e WebP | MB, entity, entityId opcional |
| forDocuments | PDF, DOC, DOCX, XLS e XLSX | MB, entity, entityId opcional |
Armazenar caminho relativo, não confiar no browser
Uploads vão para storage/uploads e são organizados como entity/ ou entity/id/. Guarde o nome retornado, Upload::resolvePath() devolve caminho relativo, não URL pública; para URL, use uploadUrl(). O arquivo passa por is_uploaded_file(), limite em bytes, MIME real via Fileinfo e whitelist de extensão.
Upload: pré-requisitos, resultado e segurança de caminho
process(): bool exige arquivo no formato PHP de $_FILES, uma configuração de entidade e um preset/configuração de tipos permitidos, por exemplo forImages() ou forDocuments(). O upload precisa ser uma transferência HTTP real; um caminho local arbitrário não satisfaz is_uploaded_file(). Antes de processar, confira Request::hasFile('avatar') e use Request::file('avatar'); não construa a classe com [] para representar campo ausente, pois o processamento espera chaves como error, tmp_name, name e size.
if (!$this->request->hasFile('avatar')) {
$this->jsonError('Envie um avatar.', 422);
}
$upload = (new \Framework\Support\Upload($this->request->file('avatar')))
->forImages(5, 'users', $this->userId());
if (!$upload->process()) {
$this->jsonError('Upload inválido.', 422, ['errors' => $upload->getErrors()]);
}
$filename = $upload->getFilename();Sucesso retorna true e disponibiliza o nome final em getFilename(); falha retorna false e acumula mensagens em getErrors(). O caminho final combina entidade, ID opcional e nome gerado.
setEntity()/setEntityId() apenas apararam barras externas; resolvePath() concatena componentes. Entidade deve vir de allowlist constante do desenvolvedor; ID deve ser validado (preferencialmente inteiro); filename deve ser exclusivamente o nome devolvido por getFilename(). Nunca aceite esses valores do usuário nem os encaminhe sem validação a resolvePath(), uploadUrl() ou exclusão de arquivo.Setters fluentes
Configuração programática disponível: setAllowedTypes(array $types): static, setAllowedExtensions(array $extensions): static, setMaxSize(int $bytes): static (bytes), setUploadDir(string $dir): static, setRandomName(bool $random): static, setPrefix(string $prefix): static, setEntity(string $entity): static e setEntityId(int|string|null $id): static. O prefixo compõe o nome quando a geração aleatória é escolhida; presets também definem tipos, limite e destino.