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
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:
- 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',
];
- 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.
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
}