Tutorials
Upload Files to MySQL on Laravel 8
Last modified: June 11, 2021Create a new Laravel project called upload-file-to-database by using the below command.
composer create-project laravel/laravel upload-file-to-database
We are creating Document Model with migration file by using artisan make command and with -m flag.
php artisan make:model Document -m
Since we are going to deal with name, file and mime property, we add them to the fillable in the Document Model.
<?php
namespace App\\Models;
use Illuminate\\Database\\Eloquent\\Factories\\HasFactory;
use Illuminate\\Database\\Eloquent\\Model;
class Document extends Model
{
use HasFactory;
protected $fillable = [
'name',
'file',
'mime',
];
}
In the migration file, we add name and mime (for identifying type of file e.g. pdf) fields as string. We also add file as MEDIUMBLOB file type by running ALTER table statement. The binary Laravel which will translate to BLOB might not be enough field length.
<?php
use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;
use Illuminate\\Support\\Facades\\DB;
class CreateDocumentsTable extends Migration
{
public function up()
{
Schema::create('documents', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('mime');
$table->timestamps();
});
DB::statement("ALTER TABLE documents ADD file MEDIUMBLOB");
}
public function down()
{
Schema::dropIfExists('documents');
}
}
Go to http://localhost/phpmyadmin/ and create a database name laravel
Ensure your databse connection details are correct in .env file.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
Now it is time to migrate (create database tables) by running artisan migrate command.
php artisan migrate
To create a controller, we make use of the make:controller artisan command.
php artisan make:controller DocumentContoller
$documents = Document::all();
will get all the documents stored in the database, and we return it to document.index view.
Before deleting a document record, we first need to get that record by using find() method ```$doc = Document::find($id);``. Then we can call the ->delete function $doc->delete();.
We can put filter to method (upload file) to type of file the can be uploaded to database e.g. pdf, jpg. We extract the mime type, file content before adding to the database.
<?php
namespace App\\Http\\Controllers;
use Illuminate\\Http\\Request;
use App\\Models\\Document;
class DocumentContoller extends Controller
{
public function index()
{
$documents = Document::all();
return view('document.index', [
'documents' => $documents,
]);
}
public function destroy($id)
{
$doc = Document::find($id);
$doc->delete();
return redirect()->route('document');
}
public function update(Request $request)
{
$request->validate([
'file' => 'mimes:jpeg,bmp,png,pdf,jpg',
'name' => 'required|max:255',
]);
if ($request->hasFile('file')) {
$path = $request->file('file')->getRealPath();
$ext = $request->file->extension();
$doc = file_get_contents($path);
$base64 = base64_encode($doc);
$mime = $request->file('file')->getClientMimeType();
Document::create([
'name'=> $request->name .'.'.$ext,
'file' => $base64,
'mime'=> $mime,
]);
return redirect()->route('document');
}
}
public function download($id)
{
$document = Document::find($id);
$file_contents = base64_decode($document->file);
return response($file_contents)
->header('Cache-Control', 'no-cache private')
->header('Content-Description', 'File Transfer')
->header('Content-Type', $document->mime)
->header('Content-length', strlen($file_contents))
->header('Content-Disposition', 'attachment; filename=' . $document->name)
->header('Content-Transfer-Encoding', 'binary');
}
}
<div class="row">
@if ($documents->count())
<h3>Documents</h3>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<td>Name</td>
<td></td>
<td></td>
</tr>
</thead>
<tbody>
@foreach ($documents as $document)
<tr>
<td>{{$document->name}}</td>
<td><a href="{{ route('document.download', $document->id) }}">Download</a></td>
<td><a href="{{ route('document.destroy', $document->id) }}">Delete</a></td>
</tr>
</tbody>
@endforeach
</table>
@endif
</div>
<form action="{{ route('document.update') }}" method="post" enctype="multipart/form-data">
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<div class="row">
<div>
<br />
@csrf
<div class="form-group">
<label for="name">End Date</label>
<input type="text" value="{{ old('name') }}" class="form-control @error('name') is-invalid @enderror" name="name" id="name" placeholder="Enter document name">
</div>
<div class="form-group">
<input type="file" class="form-control" name="file" required>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</div>
</form>
Route::get('/documents', [App\\Http\\Controllers\\DocumentContoller::class, 'index'])->name('document');
Route::post('/documents/upload', [App\\Http\\Controllers\\DocumentContoller::class, 'update'])->name('document.update');
Route::get('/documents/download/{documentId}', [App\\Http\\Controllers\\DocumentContoller::class, 'download'])->name('document.download');
Route::get('/documents/delete/{documentId}', [App\\Http\\Controllers\\DocumentContoller::class, 'destroy'])->name('document.destroy');