2015-04-09 5 views
3

Я пишу код в Laravel 5 для периодической резервной копии базы данных MySQL. Мой код до сих пор выглядит следующим образом:Laravel 5: Как скопировать локальный файл на Amazon S3?

$filename = 'database_backup_'.date('G_a_m_d_y').'.sql'; 
    $destination = storage_path() . '/backups/'; 

    $database = \Config::get('database.connections.mysql.database'); 
    $username = \Config::get('database.connections.mysql.username'); 
    $password = \Config::get('database.connections.mysql.password'); 

    $sql = "mysqldump $database --password=$password --user=$username --single-transaction >$destination" . $filename; 

    $result = exec($sql, $output); // TODO: check $result 

    // Copy database dump to S3 

    $disk = \Storage::disk('s3'); 

    // ???????????????????????????????? 
    // What goes here? 
    // ???????????????????????????????? 

Я видел в Интернете, что Solutions предложить мне делать что-то вроде:

$disk->put('my/bucket/' . $filename, file_get_contents($destination . $filename)); 

Однако для больших файлов, не так расточительно использовать file_get_contents()? Есть ли лучшие решения?

+0

Это большой вопрос, и моя цель сейчас тоже. Теперь я рассмотрю https://tuts.codingo.me/laravel-backup-amazon-s3 (который выглядит многообещающим), а также предложение ниже от пользователя @ user4603841. – Ryan

ответ

2

Глядя на документацию, единственным способом является метод put, которому требуется содержимое файла. Нет способа скопировать файл между 2 файловыми системами, поэтому, вероятно, решение, которое вы дали, в настоящий момент является единственным.

Если вы думаете об этом, наконец, при копировании файла из локальной файловой системы в s3, вам нужно иметь содержимое файла, чтобы поместить его в S3, так что на самом деле это не так расточительно, на мой взгляд.

+0

Спасибо Marcin. Я чувствовал, что это может быть расточительным, потому что file_get_contents вытащит весь файл в память до его отправки на S3. Я надеялся, что будет решение, в котором файл будет передан на S3 из локального файла. Это не имеет большого значения, если в вашем файле всего 1 или 2 мегабайта, но я могу заметить, что память больше для больших файлов. Все это - спекуляция с моей стороны, поэтому возьмите с собой соль. – clone45

+0

Есть способ сделать это с помощью Flysystem на Laravel 5, используя потоки, которые, я считаю. Возможно, стоит упомянуть Фрэнка де Йонге о том, как это сделать (автор Flysystem). В принципе, вы открываете файл через поток, вытягиваете содержимое и одновременно вставляете этот контент в файл на S3. Это экономит нагрузку на весь файл в памяти, что отлично по многим причинам. – Oddman

3

Вы всегда можете использовать файловый ресурс для потоковой передачи файла (рекомендуется для больших файлов), делая что-то вроде этого:

Storage::disk('s3')->put('my/bucket/' . $filename, fopen('path/to/local/file', 'r+')); 

Альтернативное предложение proposed here. Он использует фасад хранения Laravel для чтения потока. Основная идея что-то вроде этого:

$inputStream = Storage::disk('local')->getDriver()->readStream('/path/to/file'); 
    $destination = Storage::disk('s3')->getDriver()->getAdapter()->getPathPrefix().'/my/bucket/'; 
    Storage::disk('s3')->getDriver()->putStream($destination, $inputStream); 
+1

Я получаю только «Неверное сформированное числовое значение». Может найти решение еще – lasoweq

3

Вы можете попробовать этот код

$contents = Storage::get($file); 
Storage::disk('s3')->put($newfile,$contents); 

Как Laravel документ это простой способ я нашел, чтобы копировать данные между двумя дисками

2

Существует способ копирования файлов без необходимости загрузки содержимого файла в память.

Вам также необходимо импортировать следующие:

use League\Flysystem\MountManager; 

Теперь вы можете скопировать файл следующим образом:

$mountManager = new MountManager([ 
    's3' => \Storage::disk('s3')->getDriver(), 
    'local' => \Storage::disk('local')->getDriver(), 
]); 
$mountManager->copy('s3://path/to/file.txt', 'local://path/to/output/file.txt'); 
Смежные вопросы