Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Laravel + Spatie Backup controller & views to see and manage DB backup files in the browser
<?php
namespace App\Http\Controllers;
use Alert;
use App\Http\Requests;
use Artisan;
use Log;
use Storage;
class BackupController extends Controller
{
public function index()
{
$disk = Storage::disk(config('laravel-backup.backup.destination.disks')[0]);
$files = $disk->files(config('laravel-backup.backup.name'));
$backups = [];
// make an array of backup files, with their filesize and creation date
foreach ($files as $k => $f) {
// only take the zip files into account
if (substr($f, -4) == '.zip' && $disk->exists($f)) {
$backups[] = [
'file_path' => $f,
'file_name' => str_replace(config('laravel-backup.backup.name') . '/', '', $f),
'file_size' => $disk->size($f),
'last_modified' => $disk->lastModified($f),
];
}
}
// reverse the backups, so the newest one would be on top
$backups = array_reverse($backups);
return view("backup.backups")->with(compact('backups'));
}
public function create()
{
try {
// start the backup process
Artisan::call('backup:run');
$output = Artisan::output();
// log the results
Log::info("Backpack\BackupManager -- new backup started from admin interface \r\n" . $output);
// return the results as a response to the ajax call
Alert::success('New backup created');
return redirect()->back();
} catch (Exception $e) {
Flash::error($e->getMessage());
return redirect()->back();
}
}
/**
* Downloads a backup zip file.
*
* TODO: make it work no matter the flysystem driver (S3 Bucket, etc).
*/
public function download($file_name)
{
$file = config('laravel-backup.backup.name') . '/' . $file_name;
$disk = Storage::disk(config('laravel-backup.backup.destination.disks')[0]);
if ($disk->exists($file)) {
$fs = Storage::disk(config('laravel-backup.backup.destination.disks')[0])->getDriver();
$stream = $fs->readStream($file);
return \Response::stream(function () use ($stream) {
fpassthru($stream);
}, 200, [
"Content-Type" => $fs->getMimetype($file),
"Content-Length" => $fs->getSize($file),
"Content-disposition" => "attachment; filename=\"" . basename($file) . "\"",
]);
} else {
abort(404, "The backup file doesn't exist.");
}
}
/**
* Deletes a backup file.
*/
public function delete($file_name)
{
$disk = Storage::disk(config('laravel-backup.backup.destination.disks')[0]);
if ($disk->exists(config('laravel-backup.backup.name') . '/' . $file_name)) {
$disk->delete(config('laravel-backup.backup.name') . '/' . $file_name);
return redirect()->back();
} else {
abort(404, "The backup file doesn't exist.");
}
}
}
@extends('layouts.default')
@section('content')
<h3>Administer Database Backups</h3>
<div class="row">
<div class="col-xs-12 clearfix">
<a id="create-new-backup-button" href="{{ url('backup/create') }}" class="btn btn-primary pull-right"
style="margin-bottom:2em;"><i
class="fa fa-plus"></i> Create New Backup
</a>
</div>
<div class="col-xs-12">
@if (count($backups))
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>File</th>
<th>Size</th>
<th>Date</th>
<th>Age</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach($backups as $backup)
<tr>
<td>{{ $backup['file_name'] }}</td>
<td>{{ humanFilesize($backup['file_size']) }}</td>
<td>
{{ formatTimeStamp($backup['last_modified'], 'F jS, Y, g:ia (T)') }}
</td>
<td>
{{ diffTimeStamp($backup['last_modified']) }}
</td>
<td class="text-right">
<a class="btn btn-xs btn-default"
href="{{ url('backup/download/'.$backup['file_name']) }}"><i
class="fa fa-cloud-download"></i> Download</a>
<a class="btn btn-xs btn-danger" data-button-type="delete"
href="{{ url('backup/delete/'.$backup['file_name']) }}"><i class="fa fa-trash-o"></i>
Delete</a>
</td>
</tr>
@endforeach
</tbody>
</table>
@else
<div class="well">
<h4>There are no backups</h4>
</div>
@endif
</div>
</div>
@endsection
// Backup routes
Route::get('backup', 'BackupController@index');
Route::get('backup/create', 'BackupController@create');
Route::get('backup/download/{file_name}', 'BackupController@download');
Route::get('backup/delete/{file_name}', 'BackupController@delete');
@willvincent

This comment has been minimized.

Copy link
Owner Author

commented Apr 12, 2017

A few notes

  • The controller assumes that Sweetalerts and the laracasts flash packages & facades are available for feedback on the manual creation of a backup.
  • view template assumes bootstrap is available
  • Routes should be placed in a group that applies adequate middleware protection so that only admin users can access the routes
@christiantigre

This comment has been minimized.

Copy link

commented Sep 2, 2017

error!!!!
php artisan backup:run --only-db
Starting backup...
Dumping database pcsolutions...
Backup failed because The dump process failed with exitcode 1 : General error :
"mysqldump" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
.
Backup completed!

@Midlord

This comment has been minimized.

Copy link

commented Nov 21, 2017

Hi sir. what is your code on laravel-backup.php?

@kikoseijo

This comment has been minimized.

Copy link

commented Feb 22, 2018

Excellent, saving others people times.
Thanks a lot"

@twf-nikhila

This comment has been minimized.

Copy link

commented Jun 5, 2018

Nice, Saved a lot of time with these codes. 👍

Thanks for sharing them

@elghomariayoub

This comment has been minimized.

Copy link

commented Jun 19, 2018

Call to undefined function humanFilesize() !!!
image

@banduongtincay

This comment has been minimized.

Copy link

commented Jul 23, 2018

in public function create(), commands Artisan::call('backup:run'); not end. help me!

@nasirkhan

This comment has been minimized.

Copy link

commented Jul 25, 2018

You need to add following helper function to show the human readable file size

function humanFilesize($size, $precision = 2) {
    $units = array('B','kB','MB','GB','TB','PB','EB','ZB','YB');
    $step = 1024;
    $i = 0;

    while (($size / $step) > 0.9) {
        $size = $size / $step;
        $i++;
    }
    
    return round($size, $precision).$units[$i];
}
@shahmir811

This comment has been minimized.

Copy link

commented Sep 23, 2018

backup is not working when call it from controller,
getting the following error:

Exception message: The dump process failed with exitcode 2 : Misuse of shell builtins : mysqldump: Got error: 2004: "Can't create TCP/IP socket (10106 "Unknown error")" when trying to connect

@kingfordCris

This comment has been minimized.

Copy link

commented Oct 13, 2018

There are no commands defined in the "backup" namespace.
how is this??

@faheemdad

This comment has been minimized.

Copy link

commented Feb 27, 2019

#[kingfordCris] how to solve There are no commands defined in the "backup" namespace. problem

@hideyatsu

This comment has been minimized.

Copy link

commented Jun 18, 2019

Call to undefined function humanFilesize() !!!
image

use Spatie\Backup\Helpers\Format;

Format::humanReadableSize($disk->size($f))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.