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

Como recuperar uma imagem da Pasta Storage sem passa parâmetro na Rota Laravel?

Já tentei varias abordagens inclusive usando middleware, o código atual funciona mais tem uma falha de segurança, consigo pegar a imagem de outro usuário pela URL consequência de passa parâmetro na Rota. Alguém poderia me ajudar?

Repository GitLab :: https://gitlab.com/ronnyere/imageUploadLaravel.git

Controller

 public function getAccount()
    {
        return view('account', ['user' => Auth::user()]);
    }

    public function postSaveAccount(Request $request)
    {
        $this->validate($request, [
           'email' => 'required|email|max:100'
        ]);

        $user           = Auth::user();
        $old_email      = $user->email;
        $user->email    = $request['email'];

        $user->update();
        $file = $request->file('image');

        $file_email     = $request['email'] . '-' . $user->id . '.jpg';
        $old_file_email = $old_email . '-' . $user->id . '.jpg';
        $update = false;

        if (Storage::disk('local')->has($old_file_email)) {
            $old_file = Storage::disk('local')->get($old_file_email);
            Storage::disk('local')->put($file_email, $old_file);
            $update = true;
        }

        if ($file) {
            Storage::disk('local')->put($file_email, File::get($file));
        }

        if ($update && $old_file_email !== $file_email) {
            Storage::delete($old_file_email);
        }
        return redirect()->route('account');
    }

    public function getUserImage($file_email)
    {
        $file = Storage::disk('local')->get($file_email);
        return Response::make($file,200,[ 'Content-Type' => 'image/jpeg']);
    }

Route

Route::get('/account', [
    'uses' => 'UserController@getAccount',
    'as' => 'account'
]);

Route::post('/upateaccount', [
    'uses' => 'UserController@postSaveAccount',
    'as' => 'account.save'
]);

Route::get('/userimage/{file_email}',
    [ 'uses' => 'UserController@getUserImage',
        'as' => 'account.image',
        'middleware' => ['imageuser']
    ]);

View

@if (Storage::disk('local')->has($user->email . '-' . $user->id . '.jpg'))
        <section class="row new-post">
            <div class="col-md-6 col-md-offset-3">
                <img src="{{ route('account.image', ['file_email' => $user->email . '-' . $user->id . '.jpg']) }}" alt="" class="img-responsive">
            </div>
        </section>
@endif
11 respostas

Opa Ronnyere, tentei passar sua dúvida para pessoas que manjam de php aqui no fórum. Como é uma dúvida mais específica, talvez demore um tempo até que alguém consiga dar retorno, mas vamos tentar :).

Muito Obrigado!

Oi Ronnyere, tudo bom?

O melhor nesse caso, seria autenticar o usuario na rota. Pelo o que eu percebi, você persiste o id do usuario no nome do arquivo. Seria legal, além de persistir o id no nome do arquivo, realizar esse relacionamento no seu banco de dados.

A melhor abordagem seria criar uma tabela UserImages, ou algo do genero, com duas colunas, uma o Id do usuario e a outra o caminho para a imagem. Assim você consegue puxar do banco a imagem com o usuario que é dono.

Entretanto, se você quiser resolver unicamente o problema de autenticação, você pode verificar o id registrado no nome do arquivo, com o id do usuario logado:

 public function getUserImage($file_email)
    {
        $user = Auth::user();
        $id = $this->getIdByFileName($file_email);
        if($user->id === $id){
          $file = Storage::disk('local')->get($file_email);
          return Response::make($file,200,[ 'Content-Type' => 'image/jpeg']);
        } else {
          // devolve o response com status 401
        }
    }

// isolar esse método privado em outra classe
private function getIdByFileName($fileName){
    $fileEmailArray = explode($fileName,"-");
        $id = explode($fileEmailArray[count($fileEmailArray)-1],".")[0];
}

Assim, se o usuario não for o dono do arquivo a gente redireciona com o status 401 =)

Caso você queira um resultado mais bonito, você também pode criar um filtro para essa rota fazendo a mesma validação.

Qualquer problema é só falar.

Abraço e bons estudos.

Fiz a implementação do método que você sugeriu e no lugar do erro fiz um redirect para rota account o problema que a comparação do usuário logado com $id não esta passando mesmo quando e verdadeiro. Fiz alguma coisa errada ao implementar? Obrigado

 public function getUserImage($file_email)
    {
        $user = Auth::user();
        $id = $this->getIdByFileName($file_email);

        if($user->id === $id){
            $file = Storage::disk('local')->get($file_email);
            return Response::make($file,200,[ 'Content-Type' => 'image/jpeg']);
        } else {
            return redirect()->route('account'); // devolve o response com status 401
        }
    }

    // isolar esse método privado em outra classe
    private function getIdByFileName($fileName){
        $fileEmailArray = explode($fileName,"-");
        $id = explode($fileEmailArray[count($fileEmailArray)-1],".")[0];
    }

Opa, acho que eu deixei passar um igual a mais na comparação:

        if($user->id == $id){

Aqui eu expliquei a diferença entre os dois =)

Qualquer problema é só falar aqui!

Abraço.

Já avia tentado fazer dessa forma usando == mesmo assim a imagem não retorna a não ser que eu fale que é !== que não e o caso

if($user->id == $id){

Oi Ronnyere, da um dump nos dois ids e compartilha com a gente aqui o resultado? Algo como:

 public function getUserImage($file_email)
    {
        $user = Auth::user();
        $id = $this->getIdByFileName($file_email);
    dump($id);
    dump($user->id);
    die();
        if($user->id === $id){
            $file = Storage::disk('local')->get($file_email);
            return Response::make($file,200,[ 'Content-Type' => 'image/jpeg']);
        } else {
            return redirect()->route('account'); // devolve o response com status 401
        }
    }
solução!

Consegui resolver desta forma, retirei o parâmetro {file_email da rota }e passei para a controller ficou desta forma, muito obrigado pela força

Controller

 public function getUserImage()
    {
        $user = Auth::user();
        $image ="". $user->email . '-' . $user->id . '.jpg';
        $file = Storage::disk('local')->get($image);
        return Response::make($file,200,[ 'Content-Type' => 'image/jpeg']);

    }

Route

Route::get('/userimage',
    [ 'uses' => 'UserController@getUserImage',
        'as' => 'account.image',
        'middleware' => ['auth']
    ]);

View

 <img src="{{ route('account.image')}}">

Desde já sou Grato pela força com a duvida anterior ajudou muito Obrigado. Mais na mesma solução gostaria de tirar outra duvida como posso pre- setar as outras extensões da image na minha solução ou como posso fazer isso pegando a extensão do Banco?

ex: PNG ,JPEG

Oi Ronnyere, tudo bom?

Boa! Obrigado por compartilhar sua solução.

Você pode abrir uma outra duvida pro seu segundo problema? Assim fica mais facil de achar caso alguém passe pelo mesmo problema futuramente =)

Garanto que a gente retorna rápido.

Abraço!

Ok muito obrigado novo tópico criado.