Handling Files in Requests

Introduction

Unlike many other API helper packages, Api Auto Pilot, provides the ability to upload and handle files out-of-the-box. You can even calculate and save data provided by the file that are not present in the request body. Below you can find information on how to effectively handle file uploads. After all, who wouldn't love to have a profile picture in an app?


In this Section we will be using POSTMAN to send multipart/form-data Requests to attach files.


Uploading a File

TIP

If your request contains files, do not forget to form it as Form-Data request and not,
x-www-form-urlencoded

TIP

Before attempting to upload a file make sure to run the artisan command to link the storage folder with Laravel's public folder

php artisan storage:link

Default "File Url" Database Column

The first that we have in mind when we are thinking about uploading a file, is to store the file url on the server, in the database. Api Auto Pilot, provides a naming convention for the column that stores the file url in the database.

DANGER

New Projects Only!
This naming convention is suggested to new projects only! There is no need to refactor your database to save the file URL

Api Auto Pilot will detect if there are any uploaded files to your request. When it detects that files are present, it searches for the index that the uploaded file was linked with in the JSON body. If not set otherwise, Api Auto Pilot will assume that the default JSON index for the uploaded file is the database column name that saves the file URL when stored, which by default is called file_url. For example, if you have a Post model that on the posts table has a column that stores the post featured image for example, then Api Auto Pilot will search in the request body for the file_url index that holds the file. Let's take a look to that model

class Post extends Model
{
    use HasFactory;

    protected $fillable = [
        'body', 'title', 'user_id', 'file_url',
    ];
}

The request that we need to form to upload the file and the values is shown in the Postman screenshot below Single Post With File

TIP

If your database column. that holds the uploaded file url in the server, is not named file_url see the Manually Setting The File Url Column section.

The Request that shown in the image, if executed successfully shall return the new model in JSON followed by a 200 OK HTTP Response Code.

{
    "title": "A Post with Image Feature",
    "body": "Lorem ipsum dolor sit amet.",
    "file_url": "/storage/aap/kVTbkpz8R9Z3FgngstY0VkJeBI9r5inigwZj0pHE.jpg",
    "updated_at": "2022-11-23T16:39:12.000000Z",
    "created_at": "2022-11-23T16:39:12.000000Z",
    "id": 15
}

Manually Setting The File Url Column

Many times the database column that holds the file url is not named after a naming convention. Don't worry, Api Auto Pilot has you covered. There are 2 ways to work around this, and you can choose whatever suits you the most:

  1. The first workaround is the set a public string property in the model class, $urlColumn and set it equal to the column that holds the file Url.
    <?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
use HasFactory;

    public string $urlColumn = 'featured_image_url';

    protected $fillable = [
        'body', 'title', 'featured_image_url',
    ];
  1. The second that you have available, is to set the column name in the configuration file of package. You can set in the settings array in index, where you declare your model's namespace followed by the a database_file_column array key where you set the column name.
    Example:
// config/autopilot-api.php
 'settings' => [
        \App\Models\Post::class =>[
            'database_file_url' => 'featured_image_url'
        ]
    ] 

Both options will result in a successful response, with the request body containing the newly created model with the file url, followed by a 200 OK HTTP Status Code

{
    "title": "A Post with Image Feature",
    "body": "Lorem ipsum dolor sit amet.",
    "featured_image_url": "/storage/aap/wkRTC2MdTm1VOCiOvg5aNVrv3TOQeVSiAevDL0jq.jpg",
    "updated_at": "2022-11-23T16:57:24.000000Z",
    "created_at": "2022-11-23T16:57:24.000000Z",
    "id": 4
}

Server Calculated File Data

In many real world applications, storing just the file url, is not enough, but additional information about the file, that are calculated by the server, are needed. For example let's say that apart from the file url, you would want to save the file original client name, its size, its extension separately.

In Api Auto Pilot you can simply do that by implementing the FileManipulation Interface to your Model class, and adding the setAdditionalFileData(UploadedFile $file) Method.

Class Post extends Model implements FileManipulation{

  public function setAdditionalFileData(UploadedFile $file)
  {
     return [
       
     ];
  }
  
  
}

This method takes as a parameter an UploadedFile Instance, so you can use all the available Laravel file methods to get any additional data you want from the uploaded file.

Let's see an example. Let's get the original client name, the size, and the extension of the file that we uploaded, and save them to the database. In that case the model class would like this:

<?php

namespace App\Models;

use ApiAutoPilot\AutoPilotApi\Interfaces\FileManipulation;
use App\Http\Requests\CreatePostRequest;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

use Illuminate\Http\UploadedFile;

class Post extends Model implements FileManipulation
{
    use HasFactory;

    public string $validationRequest = CreatePostRequest::class;

 
    protected $fillable = [
        'body', 'title', 'featured_image_url', 'original_client_name', 'extension', 'size',
    ];

    public function setAdditionalFileData(UploadedFile $file):array
    {
        return [
            'original_client_name' => $file->getClientOriginalName(),
            'extension' => $file->getClientOriginalExtension(),
            'size' => $file->getSize()
        ];
    }

TIP

Do not forget to enter the additional file information to the fillable array in your model

So lets take the previous request from Postman and re-execute it.

Single Post With File

This time the response will contain the values that were returned from setAdditionalFileData() method, which were saved in the database as well.

{
    "title": "A Post with Image Feature",
    "body": "Lorem ipsum dolor sit amet.",
    "featured_image_url": "/storage/aap/wGpAybRxmFC0iLaIEjtiO1senhP2HuqT3Yp1F8ca.jpg",
    "original_client_name": "t1_505457.jpg",
    "extension": "jpg",
    "size": 39267,
    "updated_at": "2022-11-23T17:29:24.000000Z",
    "created_at": "2022-11-23T17:29:24.000000Z",
    "id": 1
}
Last Updated:
Contributors: GeorgeFourkas