Protected PDF files and images using Laravel authentication, Authenticate Laravel files, return authenticated files and images in Laravel API

Authenticated PDF or Images with Laravel API

Written By: Mohamed Atef

Published: 2022-04-23 | Comments: 0 | Category: Laravel

How to authenticate Laravel files and images using API?

Hello everyone, in this article, I am going to show you How to receive files using Laravel API and save them in Laravel storage? Then I will show you How you can retrieve these files into the response of the endpoint?

The first step is API authentication 

If you have API authentication ready in your Laravel app you can skip this part and start the article, If you don't have it you will have to check our previous post Create authentication API in Laravel 

Second Step Create a controller

I will create a controller and call it Documents

php artisan make:controller Documents

Inside the controller, I will create a function called uploadDocument

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class Documents extends Controller {
    
    protected function uploadDocument(Request $req){

    }
}

Then I will include the validation 

$validator = Validator::make($req->all(), [
    'file' => 'mimes:jpg,png,jpeg,pdf,csv|max:5120',
]);
if ($validator->fails()) {
    return response()->json($validator->errors(), 400);
}

Then use Storage class to upload the file and save it in Laravel storage

$file_name = basename( Storage::disk('public')->put('documents/', $req->file));
$link = '/storage/documents/'.$file_name;

So the entire class with the method will be

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Validator;
use Storage;

class Documents extends Controller {

    protected function uploadDocument(Request $req){
        $validator = Validator::make($req->all(), [
            'file' => 'mimes:jpg,png,jpeg,pdf,csv|max:5120',
        ]);
        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }

        $file_name = basename( Storage::disk('public')->put('documents/', $req->file));
        $link = '/storage/documents/'.$file_name;
        if($file_name){
            return response()->json([ "status" => 200, "url" => $link, "message" => "Document Uploaded successfully" ], 200);
        }else{
            return response()->json([ "status" => 400, "message" => "Unable to handle your request" ], 400);
        }   
    }
}

How to return authenticated files in response?

The first thing create a method called getDocument and add validation (to get the path) then using a File class we gonna fetch the document and with Response we can return the ContentType as 'application/pdf’ and it will be working fine with the frontend 

    public function getDocument(Request $req){
    	$validator = Validator::make($req->all(), [
            'path' => 'required',
        ]);
        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        $file = File::get('storage/documents/'.$document->path);
        $response = Response::make($file, 200);
        $response->header('Content-Type', 'application/pdf');
        return $response;
	}

and here is how you will see the response of the backend and you can check How to display authenticated PDF in the Reactjs?

How to authenticate dynamic files?

In this case, we should use a table in the DB and save the path, name, ContentType of the uploaded file and the frontend send the path and you fetch the Document depending on the path received in the request 

So while the user uploading the document we can use DB Model with these columns
path
name
contentType
size
user_id

php artisan make:model Documents -m

and in the migration file, we can set the columns 

Schema::create('documents', function (Blueprint $table) {
    $table->id();
    $table->string('path');
    $table->string('name');
    $table->string('contentType');
    $table->string('size');
    $table->unsignedBigInteger('user_id');
    $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
    $table->softDeletes($column = 'deleted_at', $precision = 0);
    $table->timestamps();
});

Then in the function of uploadDocument we will only add a small code to register the file in our DB

    protected function uploadDocument(Request $req){
        $validator = Validator::make($req->all(), [
            'file' => 'mimes:jpg,png,jpeg,pdf,csv|max:5120',
        ]);
        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        $file_name = basename( Storage::disk('public')->put('documents/', $req->file));
        $link = '/storage/documents/'.$file_name;

        //Register the file in DB
        $document = Documents::create([
            'path' => $link,
            'name' => $file_name,
            'contentType' => $req->file->getMimeType(),
            'size' => $req->file->getSize(),
            'user_id' => $user->id 
        ]);

        if($file_name){
            return response()->json([ "status" => 200, "url" => $link, "message" => "Document Uploaded successfully" ], 200);
        }else{
            return response()->json([ "status" => 400, "message" => "Unable to handle your request" ], 400);
        }   
    }

and to get the uploaded file using the path or the name

	public function getDocument(Request $req){
        $validator = Validator::make($req->all(), [
            'path' => 'required',
        ]);
        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        $user = Auth::guard('api')->user();
        $document = Document::where('name', '=', $req->path)->with('user')->get()->first();
        //If no Document return 404
        if(!$document){
            return abort(404);
        }
        // If Uploaded user is not the user who own the request return 404 or 401
        if($document->user->id != $user->id){
            return abort(404);
        }
        if($document->path){
            // $file = Storage::disk('public')->get($document->path); 
            $file = File::get('storage/documents/'.$document->name);
            $response = Response::make($file, 200);
            $response->header('Content-Type', 'application/pdf');
            return $response;
        }else{
            return abort(404);
        }
    }

That's All, If you have any questions or bugs I will be happy to response in the comments below,
Good Luck

Comments

There is no comments yet

Leave a comment

Join us

Join our community and get the chance to solve your code issues & share your opinion with us

Sign up Now

Related posts

Create authentication API in Laravel
Publish date: 2022-04-22 | Comments: 0