by Devin Yang

建立於: 1年前 ( 更新: 1年前 )

SFTP的安裝及設定不在本篇討論範圍,如果您想了解,建議可以看另一篇
https://www.ccc.tc/article/Laravel-SFTP-Driver-Configuration

本篇我要用極快速的Sample Demo我如何用自建的artisan的指令同步遠端的資料到本地端。
或許有人會問為何不用rsync,呀本篇就是要介紹用Storage的方式同步檔案。🤪

在這裡,我們可以看到Laravel框架帶來的好處,
像是Storage也可以換成自己的Google Drive,有機會我再來寫一篇。
設計上,我讓本地端檔案上傳時,也透過queue的機制,自動上傳一份到雲端(Google Drive),
本地端的檔案上刪除,同步刪除雲端檔案,使用者下載檔案時,會由雲端下載,雲端還沒檔案時由本地端下載。
但我自己的經驗,用戶也要登入Google才能下載我的Google Drive檔案,好像扯遠了,我們回到正題。

先直接看code吧,我在config/filesystems.php設定了一個sftp磁碟叫ccc。

'ccc' => [
    'driver' => 'sftp',
    'host' => '192.168.99.2',
    'username' => 'dlaravel',
    'privateKey' => '/home/dlaravel/.ssh/id_ed25519',
    'port' => 2258,
    'root' => '/var/www/html/storage/app/public',
    'url'=>'https://www.ccc.tc/storage',
],

然後我在routes/console.php新增了一個新的artisan命令

//同步遠端資料
Artisan::command("fs:sync {disk} {directory}", function ($disk, $directory) {
    //指定磁碟,列出檔案內容,在本篇文章會列出我遠端主機的images目錄內的檔案。
    $files = Storage::disk($disk)->files($directory);
    foreach ($files as $file) {
        //因為檔案從遠端抓到本地端會有時間差,透過這個功能,下載檔案,並把檔案調整為遠端主機的修改時間
        $download_to_local = function () use ($disk, $file) {
            $file_content = Storage::disk($disk)->get($file);//取得遠端檔案內容
            Storage::disk("local")->put('public/' . $file, $file_content); //把遠端檔案內容存用相同的檔名存入本地端
            $lastModifiedTime = Storage::disk($disk)->lastModified($file); //遠端檔案最後修改時間
            $localFile  = Storage::disk("local")->path("public/" . $file); //取得本地端檔案路徑
            //調整修改時間與遠端檔案相同
            touch($localFile, $lastModifiedTime);
        };
		//同步處理        
        if (!Storage::disk("local")->exists('public/' . $file)) {
        	//上方條件,檢查本地端的檔案存不存在就下載在存檔
            $download_to_local(); //下載並且修正時間
            echo sprintf("%s created.\n", $file);
        } elseif (Storage::disk($disk)->lastModified($file) > Storage::disk("local")->lastModified('public/' . $file)) {
            //上面的條件,因遠端及本地都有相同檔案,比較修改時間,如果遠端主機的時間大於本地端,
            //代表遠端的檔案有更新了,就進行檔案更新。
            $download_to_local(); //下載並且修正時間
            echo sprintf("%s updated.\n", $file);
        } else {
            //echo sprintf("sync skip %s, already up to date.\n", $file);
        }
    }
});

如果你們有注意到上面的程式碼,我用Laravel的Storage提供的get及put功能,直接搞定遠端主機的抓檔及本地端主機的存檔,真好用。😆

如下畫面,同步完成囉

我們直接登到這兩個網站查看,修改時間是一致的,這結果是我想要的。

如果我們在遠端的檔案隨便touhc一下,更新修改時間,用來模擬遠端檔案被修改了.

我們再從本地端執行一次同步指令,因為我邊打邊貼圖,所以下面的畫面中多了上方我貼的三張圖檔created,
,但您可看到我touch的檔案被更新了,後面顯示updated.🤣

images/sqGaCIj8WkZFKvifC1TITn81QocunOyHYQq0m7Ae.png updated.

實際操作畫面

不管怎麼說,他真的有作用. 😁
 

Tags: laravel storage

Devin Yang

文章內容無法一一說明,如果您有什麼不了解處,歡迎提問哦:)

No Comment

Post your comment

需要登入才可留言!