Blog EspecializaTi
Carlos Ferreira Por: Carlos Ferreira Comentar

Upload de arquivos no laravel com Request

Em uma aplicação é muito comum surgir a necessidade de fazer upload de arquivos, e neste tutorial vou ensinar como fazer uploads de arquivos no laravel utilizando os recursos da classe Request, não iremos abordar os recursos File Storage.

Primeiro passo é entender as configurações de upload no arquivo /config/filesystems.php

Neste arquivo a primeira configuração é “default” que define qual “disks” de configuração de uploads que a aplicação vai manter por default. Por default é local:

'default' => env('FILESYSTEM_DRIVER', 'local'),

Ao deixar os dados assim com o padrão de upload como “local” no array “disks” vai pegar as configurações do array “local”:

'local' => [
    'driver' => 'local',
    'root' => storage_path('app'),
],

drive: Como será feito o upload, se deixar “local” os arquivos ficaram armazenados na própria aplicação, também é possível configurar transferência automática via FTP ou até mesmo enviar para a Amazon com s3. Os valores suportados são: “local”, “ftp”, “s3” e “rackspace”.

root: É o diretório onde ficará armazenado os arquivos no momento que fizer upload. O helper storage_path() aponta para o diretório storage/, e como está assim storage_path(‘app’) define que o diretório de upload será para storage/app/

Quando for fazer o upload de algum arquivo restrito, ou até mesmo que vai disponibilizar o download através de response ou exibir apenas o item, pode deixar essa configuração. Porém se for fazer upload de imagens/arquivos que precisarão ser exibidos posteriormente em uma view por exemplo, precisa utilizar as configurações de “public”, então no “default” configure como “public” veja:

'default' => env('FILESYSTEM_DRIVER', 'public'),

Ao fazer isso vai utilizar essas configurações de “disks”:

'public' => [
    'driver' => 'local',
    'root' => storage_path('app/public'),
    'url' => env('APP_URL').'/storage',
    'visibility' => 'public',
],

Com essas configurações os uploads ficaram em storage/app/public

Qual a vantagem?
Se for exibir as imagens em uma listagem na view vai ser mais simples de exibir.
Não é possível exibir uma imagem que está em storage/ em uma listagem na view, só é possível exibir itens na view que estão em /public (que são o conteúdo publico de uma aplicação web (imagens, fontes, css, js)).

Como resolver?
É possível através do próprio artisan criar um link simbólico de storage/app/public para dentro public/storage rode este comando:

php artisan storage:link

Esse comando cria um link simbólico em public/storage que aponta para storage/app/public, ou seja, agora todos os arquivos disponíveis neste diretório estarão disponível publicamente na aplicação e agora será possível acessa-los facilmente.

 

NOTA. Antes de tentar fazer o upload é importante que o formulário que será utilizado para o envio dos arquivos (upload) contenha o atributo enctype=”multipart/form-data”, exemplo:

<form action="url-aqui" method="post" enctype="multipart/form-data">
    <input type="file" name="image">
    ...
</form>

 
 
 

Recuperar o arquivo de upload:

Neste exemplo nosso campo de imagem tem o nome “image”, e para recuperar pode utilizar estas ducas formas:

$file = $request->file('image');
// ou
$file = $request->image;

Verificações:
É importante antes de fazer o upload verificar se informou o arquivo e se é um arquivo válido:

// Se informou o arquivo, retorna um boolean
$file = $request->hasFile('image')

// Se é válido, retorna um boolean
$file = $request->file('image')->isValid()

Recuperar algumas informações do arquivo:
É possível recuperar diversas informações a respeito do arquivo antes de fazer o upload, veja algumas das opções:

// Retorna mime type do arquivo (Exemplo image/png)
$request->imagem->getMimeType()

// Retorna o nome original do arquivo
$request->imagem->getClientOriginalName() 

// Extensão do arquivo
$request->imagem->getClientOriginalExtension()
$request->imagem->extension()

// Tamanho do arquivo
$request->imagem->getClientSize()

Mais detalhes na documentação oficial

 

Fazendo upload:
É bem simples o upload de arquivos no laravel, basta fazer assim:

$upload = $request->image->store('products');

O arquivo será salvo em storage/app/public/products/ com um nome aleatório

É possível informar também o “driver” de upload no momento de salvar:

$upload = $request->image->store('products', 's3');

Neste exemplo o upload vai pegar as configurações de “s3” e fazer o upload para a Amazon.

Se quiser salvar o arquivo com um nome especial, é possível utilizar o método storeAs(), veja como:

$upload = $request->image->storeAs('products', 'novonome.jpg');
// Neste caso será salvo em storage/app/public/products/novonome.jpg

Também é possível informar dinâmicamente qual é o driver de armazenamento, veja o exemplo:

$upload = $request->image->storeAs('products', 'novonome.jpg', 's3');

 
 
 

Um exemplo real:

Para finalizar vamos fazer um exemplo real, onde vamos fazer o upload do arquivo para storage/app/public/categories/ com nomes personalizados criados pela nossa própria aplicação, veja:

/**
 * Store a newly created resource in storage.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
public function store(Request $request)
{
    // Define o valor default para a variável que contém o nome da imagem 
    $nameFile = null;

    // Verifica se informou o arquivo e se é válido
    if ($request->hasFile('image') && $request->file('image')->isValid()) {
        
        // Define um aleatório para o arquivo baseado no timestamps atual
        $name = uniqid(date('HisYmd'));

        // Recupera a extensão do arquivo
        $extension = $request->image->extension();

        // Define finalmente o nome
        $nameFile = "{$name}.{$extension}";

        // Faz o upload:
        $upload = $request->image->storeAs('categories', $nameFile);
        // Se tiver funcionado o arquivo foi armazenado em storage/app/public/categories/nomedinamicoarquivo.extensao

        // Verifica se NÃO deu certo o upload (Redireciona de volta)
        if ( !$upload )
            return redirect()
                        ->back()
                        ->with('error', 'Falha ao fazer upload')
                        ->withInput();

    }
}

 
 
 

Como exibir?

Como criamos um link simbólico de public/storage que aponta para storage/app/public é possível exibir facilmente na view o arquivo de imagem, veja um exemplo de uma listagem dinâmica de categorias:

@foreach( $categories as $category )
    {{ $category->name }}

    <img src="{{ url("categories/{$category->image}") }}" alt="{{ $category->name }}">
@endforeach

 
 

Carlos Ferreira

Sobre o Autor:

Carlos Ferreira

Carlos Ferreira é Analista de Sistemas Experiente, Empreendedor, Fundador da empresa EspecializaTi. Certificações: Comptia Linux +, LPI, Novell Certification.

Todos os direitos reservados © 2021 - EspecializaTi. É proibida a reprodução total ou parcial deste conteúdo.