跳至內容

檔案儲存

簡介

Laravel 借助 Frank de Jonge 精彩的 Flysystem PHP 套件,提供強大的檔案系統抽象。Laravel Flysystem 整合提供了簡單的驅動程式,可與本機檔案系統、SFTP 和 Amazon S3 搭配使用。更好的是,在您的本機開發機器和生產伺服器之間切換這些儲存選項非常簡單,因為每個系統的 API 都保持不變。

設定

Laravel 的檔案系統設定檔位於 config/filesystems.php。在此檔案中,您可以設定所有檔案系統「磁碟」。每個磁碟代表特定的儲存驅動程式和儲存位置。設定檔中包含每個支援的驅動程式的範例設定,因此您可以修改設定以反映您的儲存偏好和認證。

local 驅動程式與儲存在執行 Laravel 應用程式的伺服器本機上的檔案互動,而 s3 驅動程式則用於寫入 Amazon 的 S3 雲端儲存服務。

lightbulb - Laravel 框架

您可以設定任意數量的磁碟,甚至可以有多個使用相同驅動程式的磁碟。

本地驅動程式

當使用 local 驅動程式時,所有檔案作業都相對於 filesystems 設定檔中定義的 root 目錄。預設情況下,此值設定為 storage/app 目錄。因此,以下方法會寫入 storage/app/example.txt

use Illuminate\Support\Facades\Storage;
 
Storage::disk('local')->put('example.txt', 'Contents');

公開磁碟

您的應用程式 filesystems 設定檔中包含的 public 磁碟適用於將公開存取的檔案。預設情況下,public 磁碟使用 local 驅動程式並將其檔案儲存在 storage/app/public 中。

若要讓這些檔案可從網路上存取,您應該建立從 public/storagestorage/app/public 的符號連結。使用此資料夾慣例會將您的公開存取檔案保留在一個目錄中,當使用零停機部署系統(例如 Envoyer)時,可以輕鬆地跨部署共用。

若要建立符號連結,您可以使用 storage:link Artisan 命令

php artisan storage:link

一旦檔案儲存完畢並且已建立符號連結,您可以使用 asset 輔助函數建立指向檔案的 URL

echo asset('storage/file.txt');

您可以在 filesystems 設定檔中設定其他符號連結。當您執行 storage:link 命令時,將會建立每個設定的連結

'links' => [
public_path('storage') => storage_path('app/public'),
public_path('images') => storage_path('app/images'),
],

可以使用 storage:unlink 命令來銷毀您設定的符號連結

php artisan storage:unlink

驅動程式先決條件

S3 驅動程式設定

在使用 S3 驅動程式之前,您需要透過 Composer 套件管理器安裝 Flysystem S3 套件

composer require league/flysystem-aws-s3-v3 "^3.0" --with-all-dependencies

S3 磁碟設定陣列位於您的 config/filesystems.php 設定檔中。通常,您應該使用以下由 config/filesystems.php 設定檔參考的環境變數來設定您的 S3 資訊和認證

AWS_ACCESS_KEY_ID=<your-key-id>
AWS_SECRET_ACCESS_KEY=<your-secret-access-key>
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=<your-bucket-name>
AWS_USE_PATH_STYLE_ENDPOINT=false

為方便起見,這些環境變數符合 AWS CLI 使用的命名慣例。

FTP 驅動程式設定

在使用 FTP 驅動程式之前,您需要透過 Composer 套件管理器安裝 Flysystem FTP 套件

composer require league/flysystem-ftp "^3.0"

Laravel 的 Flysystem 整合與 FTP 搭配使用效果良好;但是,框架的預設 config/filesystems.php 設定檔中未包含範例設定。如果您需要設定 FTP 檔案系統,可以使用下面的設定範例

'ftp' => [
'driver' => 'ftp',
'host' => env('FTP_HOST'),
'username' => env('FTP_USERNAME'),
'password' => env('FTP_PASSWORD'),
 
// Optional FTP Settings...
// 'port' => env('FTP_PORT', 21),
// 'root' => env('FTP_ROOT'),
// 'passive' => true,
// 'ssl' => true,
// 'timeout' => 30,
],

SFTP 驅動程式設定

在使用 SFTP 驅動程式之前,您需要透過 Composer 套件管理器安裝 Flysystem SFTP 套件

composer require league/flysystem-sftp-v3 "^3.0"

Laravel 的 Flysystem 整合與 SFTP 搭配使用效果良好;但是,框架的預設 config/filesystems.php 設定檔中未包含範例設定。如果您需要設定 SFTP 檔案系統,可以使用下面的設定範例

'sftp' => [
'driver' => 'sftp',
'host' => env('SFTP_HOST'),
 
// Settings for basic authentication...
'username' => env('SFTP_USERNAME'),
'password' => env('SFTP_PASSWORD'),
 
// Settings for SSH key based authentication with encryption password...
'privateKey' => env('SFTP_PRIVATE_KEY'),
'passphrase' => env('SFTP_PASSPHRASE'),
 
// Settings for file / directory permissions...
'visibility' => 'private', // `private` = 0600, `public` = 0644
'directory_visibility' => 'private', // `private` = 0700, `public` = 0755
 
// Optional SFTP Settings...
// 'hostFingerprint' => env('SFTP_HOST_FINGERPRINT'),
// 'maxTries' => 4,
// 'passphrase' => env('SFTP_PASSPHRASE'),
// 'port' => env('SFTP_PORT', 22),
// 'root' => env('SFTP_ROOT', ''),
// 'timeout' => 30,
// 'useAgent' => true,
],

範圍和唯讀檔案系統

範圍磁碟允許您定義一個檔案系統,其中所有路徑都會自動加上給定的路徑前置詞。在建立範圍檔案系統磁碟之前,您需要透過 Composer 套件管理器安裝額外的 Flysystem 套件

composer require league/flysystem-path-prefixing "^3.0"

您可以透過定義使用 scoped 驅動程式的磁碟,來建立任何現有檔案系統磁碟的路徑範圍實例。例如,您可以建立一個將現有 s3 磁碟範圍設定為特定路徑前置詞的磁碟,然後使用您的範圍磁碟進行的每個檔案作業都將使用指定的字首

's3-videos' => [
'driver' => 'scoped',
'disk' => 's3',
'prefix' => 'path/to/videos',
],

「唯讀」磁碟允許您建立不允許寫入作業的檔案系統磁碟。在使用 read-only 設定選項之前,您需要透過 Composer 套件管理器安裝額外的 Flysystem 套件

composer require league/flysystem-read-only "^3.0"

接下來,您可以在一個或多個磁碟的設定陣列中包含 read-only 設定選項

's3-videos' => [
'driver' => 's3',
// ...
'read-only' => true,
],

Amazon S3 相容檔案系統

預設情況下,您應用程式的 filesystems 設定檔包含 s3 磁碟的磁碟設定。除了使用此磁碟與 Amazon S3 互動外,您還可以將其用於與任何 S3 相容的檔案儲存服務互動,例如 MinIODigitalOcean Spaces

通常,在更新磁碟的認證以符合您計劃使用的服務的認證之後,您只需要更新 endpoint 設定選項的值。此選項的值通常透過 AWS_ENDPOINT 環境變數定義

'endpoint' => env('AWS_ENDPOINT', 'https://minio:9000'),

MinIO

為了讓 Laravel 的 Flysystem 整合在使用 MinIO 時產生正確的 URL,您應該定義 AWS_URL 環境變數,使其與您應用程式的本機 URL 相符,並在 URL 路徑中包含儲存貯體名稱

AWS_URL=http://localhost:9000/local
exclamation - Laravel 框架

如果用戶端無法存取 endpoint,則透過 temporaryUrl 方法產生臨時儲存 URL 可能無法在使用 MinIO 時運作。

取得磁碟實例

可以使用 Storage 外觀模式與任何設定的磁碟互動。例如,您可以使用外觀模式上的 put 方法在預設磁碟上儲存化身。如果您在沒有先呼叫 disk 方法的情況下在外觀模式上呼叫方法,則該方法會自動傳遞給預設磁碟

use Illuminate\Support\Facades\Storage;
 
Storage::put('avatars/1', $content);

如果您的應用程式與多個磁碟互動,您可以使用 Storage 外觀模式上的 disk 方法來處理特定磁碟上的檔案

Storage::disk('s3')->put('avatars/1', $content);

隨需磁碟

有時候您可能希望在運行時使用給定的配置建立磁碟,而該配置實際上並不存在於應用程式的 filesystems 配置檔案中。為了實現這一點,您可以將配置陣列傳遞給 Storage 外觀的 build 方法。

use Illuminate\Support\Facades\Storage;
 
$disk = Storage::build([
'driver' => 'local',
'root' => '/path/to/root',
]);
 
$disk->put('image.jpg', $content);

檢索檔案

get 方法可用於檢索檔案的內容。該方法將返回檔案的原始字串內容。請記住,所有檔案路徑都應相對於磁碟的「根」位置指定。

$contents = Storage::get('file.jpg');

如果您正在檢索的檔案包含 JSON,您可以使用 json 方法檢索檔案並解碼其內容。

$orders = Storage::json('orders.json');

exists 方法可用於確定檔案是否存在於磁碟上。

if (Storage::disk('s3')->exists('file.jpg')) {
// ...
}

missing 方法可用於確定檔案是否在磁碟上遺失。

if (Storage::disk('s3')->missing('file.jpg')) {
// ...
}

下載檔案

download 方法可用於產生一個響應,強制使用者的瀏覽器下載給定路徑的檔案。 download 方法接受一個檔案名稱作為方法的第二個參數,這將決定使用者下載檔案時看到的檔案名稱。最後,您可以將 HTTP 標頭的陣列作為方法的第三個參數傳遞。

return Storage::download('file.jpg');
 
return Storage::download('file.jpg', $name, $headers);

檔案網址

您可以使用 url 方法取得給定檔案的 URL。如果您正在使用 local 驅動程式,這通常只會在給定路徑前面加上 /storage,並返回檔案的相對 URL。如果您正在使用 s3 驅動程式,則會返回完整的遠端 URL。

use Illuminate\Support\Facades\Storage;
 
$url = Storage::url('file.jpg');

當使用 local 驅動程式時,所有應該公開訪問的檔案都應該放置在 storage/app/public 目錄中。此外,您應該在 public/storage 建立一個指向 storage/app/public 目錄的符號連結

exclamation - Laravel 框架

當使用 local 驅動程式時,url 的返回值不會進行 URL 編碼。因此,我們建議始終使用將產生有效 URL 的名稱來儲存檔案。

URL 主機客製化

如果您想修改使用 Storage 外觀產生的 URL 的主機,您可以在磁碟的配置陣列中新增或變更 url 選項。

'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
'throw' => false,
],

臨時網址

使用 temporaryUrl 方法,您可以為使用 locals3 驅動程式儲存的檔案建立臨時 URL。此方法接受一個路徑和一個 DateTime 實例,指定 URL 應該過期的時間。

use Illuminate\Support\Facades\Storage;
 
$url = Storage::temporaryUrl(
'file.jpg', now()->addMinutes(5)
);

啟用本地臨時 URL

如果您在 local 驅動程式引入臨時 URL 支援之前開始開發應用程式,您可能需要啟用本地臨時 URL。為此,請在 config/filesystems.php 配置檔案中,將 serve 選項新增到您的 local 磁碟的配置陣列中。

'local' => [
'driver' => 'local',
'root' => storage_path('app/private'),
'serve' => true,
'throw' => false,
],

S3 請求參數

如果您需要指定其他S3 請求參數,您可以將請求參數的陣列作為 temporaryUrl 方法的第三個參數傳遞。

$url = Storage::temporaryUrl(
'file.jpg',
now()->addMinutes(5),
[
'ResponseContentType' => 'application/octet-stream',
'ResponseContentDisposition' => 'attachment; filename=file2.jpg',
]
);

客製化臨時 URL

如果您需要客製化特定儲存磁碟的臨時 URL 的建立方式,可以使用 buildTemporaryUrlsUsing 方法。例如,如果您有一個控制器允許您下載透過通常不支援臨時 URL 的磁碟儲存的檔案,這會很有用。通常,此方法應該從服務提供者的 boot 方法中呼叫。

<?php
 
namespace App\Providers;
 
use DateTime;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
 
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Storage::disk('local')->buildTemporaryUrlsUsing(
function (string $path, DateTime $expiration, array $options) {
return URL::temporarySignedRoute(
'files.download',
$expiration,
array_merge($options, ['path' => $path])
);
}
);
}
}

臨時上傳 URL

exclamation - Laravel 框架

產生臨時上傳 URL 的功能僅受 s3 驅動程式支援。

如果您需要產生一個臨時 URL,可用於直接從您的用戶端應用程式上傳檔案,可以使用 temporaryUploadUrl 方法。此方法接受一個路徑和一個 DateTime 實例,指定 URL 應該過期的時間。 temporaryUploadUrl 方法會傳回一個關聯陣列,可以將其解構為上傳 URL 和上傳請求中應該包含的標頭。

use Illuminate\Support\Facades\Storage;
 
['url' => $url, 'headers' => $headers] = Storage::temporaryUploadUrl(
'file.jpg', now()->addMinutes(5)
);

此方法主要用於需要用戶端應用程式直接將檔案上傳到雲端儲存系統(例如 Amazon S3)的無伺服器環境中。

檔案中繼資料

除了讀取和寫入檔案之外,Laravel 還可以提供關於檔案本身的資訊。例如,size 方法可用於取得檔案的大小(以位元組為單位)。

use Illuminate\Support\Facades\Storage;
 
$size = Storage::size('file.jpg');

lastModified 方法會傳回檔案上次修改的 UNIX 時間戳記。

$time = Storage::lastModified('file.jpg');

給定檔案的 MIME 類型可以透過 mimeType 方法取得。

$mime = Storage::mimeType('file.jpg');

檔案路徑

您可以使用 path 方法取得給定檔案的路徑。如果您正在使用 local 驅動程式,這會傳回檔案的絕對路徑。如果您正在使用 s3 驅動程式,此方法會傳回檔案在 S3 儲存桶中的相對路徑。

use Illuminate\Support\Facades\Storage;
 
$path = Storage::path('file.jpg');

儲存檔案

put 方法可用於將檔案內容儲存到磁碟上。您也可以將 PHP resource 傳遞給 put 方法,這將使用 Flysystem 的底層串流支援。請記住,所有檔案路徑都應相對於為磁碟配置的「根」位置指定。

use Illuminate\Support\Facades\Storage;
 
Storage::put('file.jpg', $contents);
 
Storage::put('file.jpg', $resource);

寫入失敗

如果 put 方法(或其他「寫入」操作)無法將檔案寫入磁碟,則會傳回 false

if (! Storage::put('file.jpg', $contents)) {
// The file could not be written to disk...
}

如果您願意,您可以在檔案系統磁碟的配置陣列中定義 throw 選項。當此選項定義為 true 時,當寫入操作失敗時,put 等「寫入」方法會拋出 League\Flysystem\UnableToWriteFile 的實例。

'public' => [
'driver' => 'local',
// ...
'throw' => true,
],

在檔案前附加或後附加

prependappend 方法允許您寫入檔案的開頭或結尾。

Storage::prepend('file.log', 'Prepended Text');
 
Storage::append('file.log', 'Appended Text');

複製和移動檔案

copy 方法可用於將現有檔案複製到磁碟上的新位置,而 move 方法可用於將現有檔案重新命名或移動到新位置。

Storage::copy('old/file.jpg', 'new/file.jpg');
 
Storage::move('old/file.jpg', 'new/file.jpg');

自動串流

將檔案串流到儲存體可大幅減少記憶體使用量。如果您希望 Laravel 自動管理將給定檔案串流到您的儲存位置,可以使用 putFileputFileAs 方法。此方法接受 Illuminate\Http\FileIlluminate\Http\UploadedFile 實例,並會自動將檔案串流到您想要的位置。

use Illuminate\Http\File;
use Illuminate\Support\Facades\Storage;
 
// Automatically generate a unique ID for filename...
$path = Storage::putFile('photos', new File('/path/to/photo'));
 
// Manually specify a filename...
$path = Storage::putFileAs('photos', new File('/path/to/photo'), 'photo.jpg');

關於 putFile 方法,有幾件事需要注意。請注意,我們只指定了目錄名稱,而不是檔案名稱。預設情況下,putFile 方法會產生一個唯一 ID 作為檔案名稱。檔案的副檔名將透過檢查檔案的 MIME 類型來確定。檔案的路徑將由 putFile 方法傳回,因此您可以將路徑(包括產生的檔案名稱)儲存在資料庫中。

putFileputFileAs 方法也接受一個參數來指定儲存檔案的「可見性」。如果您將檔案儲存在雲端磁碟(例如 Amazon S3)上,並且希望透過產生的 URL 公開存取檔案,這會特別有用。

Storage::putFile('photos', new File('/path/to/photo'), 'public');

檔案上傳

在 Web 應用程式中,儲存檔案最常見的用例之一是儲存使用者上傳的檔案,例如照片和文件。 Laravel 可以使用上傳檔案實例上的 store 方法,輕鬆儲存上傳的檔案。使用您希望儲存上傳檔案的路徑呼叫 store 方法。

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
 
class UserAvatarController extends Controller
{
/**
* Update the avatar for the user.
*/
public function update(Request $request): string
{
$path = $request->file('avatar')->store('avatars');
 
return $path;
}
}

關於此範例,有幾件事需要注意。請注意,我們只指定了目錄名稱,而不是檔案名稱。預設情況下,store 方法會產生一個唯一 ID 作為檔案名稱。檔案的副檔名將透過檢查檔案的 MIME 類型來確定。檔案的路徑將由 store 方法傳回,因此您可以將路徑(包括產生的檔案名稱)儲存在資料庫中。

您也可以在上 Storage 外觀呼叫 putFile 方法,以執行與上述範例相同的檔案儲存操作。

$path = Storage::putFile('avatars', $request->file('avatar'));

指定檔案名稱

如果您不希望自動為您儲存的檔案分配檔案名稱,可以使用 storeAs 方法,該方法接收路徑、檔案名稱和(可選)磁碟作為其參數。

$path = $request->file('avatar')->storeAs(
'avatars', $request->user()->id
);

您也可以在 Storage 外觀上使用 putFileAs 方法,這會執行與上述範例相同的檔案儲存操作。

$path = Storage::putFileAs(
'avatars', $request->file('avatar'), $request->user()->id
);
exclamation - Laravel 框架

不可列印和無效的 Unicode 字元會自動從檔案路徑中移除。因此,您可能希望在將檔案路徑傳遞給 Laravel 的檔案儲存方法之前,先對其進行清理。檔案路徑會使用 League\Flysystem\WhitespacePathNormalizer::normalizePath 方法進行正規化。

指定磁碟

預設情況下,此上傳檔案的 store 方法將使用您的預設磁碟。如果您想指定其他磁碟,請將磁碟名稱作為第二個參數傳遞給 store 方法。

$path = $request->file('avatar')->store(
'avatars/'.$request->user()->id, 's3'
);

如果您正在使用 storeAs 方法,您可以將磁碟名稱作為方法的第三個參數傳遞。

$path = $request->file('avatar')->storeAs(
'avatars',
$request->user()->id,
's3'
);

其他上傳檔案資訊

如果您想取得上傳檔案的原始名稱和副檔名,可以使用 getClientOriginalNamegetClientOriginalExtension 方法。

$file = $request->file('avatar');
 
$name = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();

但是,請記住,getClientOriginalNamegetClientOriginalExtension 方法被認為是不安全的,因為檔案名稱和副檔名可能會被惡意使用者竄改。因此,您通常應該優先使用 hashNameextension 方法來取得給定檔案上傳的名稱和副檔名。

$file = $request->file('avatar');
 
$name = $file->hashName(); // Generate a unique, random name...
$extension = $file->extension(); // Determine the file's extension based on the file's MIME type...

檔案可見性

在 Laravel 的 Flysystem 整合中,「可見性」是多個平台上的檔案權限的抽象概念。檔案可以宣告為 publicprivate。當檔案宣告為 public 時,表示您通常希望其他人可以存取該檔案。例如,當使用 S3 驅動程式時,您可以檢索 public 檔案的 URL。

您可以在透過 put 方法寫入檔案時設定可見性。

use Illuminate\Support\Facades\Storage;
 
Storage::put('file.jpg', $contents, 'public');

如果檔案已經儲存,則可以透過 getVisibilitysetVisibility 方法檢索和設定其可見性。

$visibility = Storage::getVisibility('file.jpg');
 
Storage::setVisibility('file.jpg', 'public');

當與上傳的檔案互動時,您可以使用 storePubliclystorePubliclyAs 方法來儲存具有 public 可見性的上傳檔案。

$path = $request->file('avatar')->storePublicly('avatars', 's3');
 
$path = $request->file('avatar')->storePubliclyAs(
'avatars',
$request->user()->id,
's3'
);

本地檔案和可見性

當使用 local 驅動程式時,public 可見性會轉換為目錄的 0755 權限以及檔案的 0644 權限。您可以在應用程式的 filesystems 設定檔中修改權限對應。

'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'permissions' => [
'file' => [
'public' => 0644,
'private' => 0600,
],
'dir' => [
'public' => 0755,
'private' => 0700,
],
],
'throw' => false,
],

刪除檔案

delete 方法接受單一檔案名稱或要刪除的檔案陣列。

use Illuminate\Support\Facades\Storage;
 
Storage::delete('file.jpg');
 
Storage::delete(['file.jpg', 'file2.jpg']);

如有必要,您可以指定應從哪個磁碟刪除檔案。

use Illuminate\Support\Facades\Storage;
 
Storage::disk('s3')->delete('path/file.jpg');

目錄

取得目錄中的所有檔案

files 方法會回傳指定目錄中所有檔案的陣列。如果您想要取得指定目錄(包括所有子目錄)中所有檔案的清單,您可以使用 allFiles 方法。

use Illuminate\Support\Facades\Storage;
 
$files = Storage::files($directory);
 
$files = Storage::allFiles($directory);

取得目錄中的所有目錄

directories 方法會回傳指定目錄中所有目錄的陣列。此外,您可以使用 allDirectories 方法來取得指定目錄及其所有子目錄中的所有目錄清單。

$directories = Storage::directories($directory);
 
$directories = Storage::allDirectories($directory);

建立目錄

makeDirectory 方法將會建立指定的目錄,包括任何需要的子目錄。

Storage::makeDirectory($directory);

刪除目錄

最後,可以使用 deleteDirectory 方法來移除目錄及其所有檔案。

Storage::deleteDirectory($directory);

測試

Storage facade 的 fake 方法可讓您輕鬆產生一個虛擬磁碟,結合 Illuminate\Http\UploadedFile 類別的檔案產生工具,能大幅簡化檔案上傳的測試。例如:

<?php
 
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
 
test('albums can be uploaded', function () {
Storage::fake('photos');
 
$response = $this->json('POST', '/photos', [
UploadedFile::fake()->image('photo1.jpg'),
UploadedFile::fake()->image('photo2.jpg')
]);
 
// Assert one or more files were stored...
Storage::disk('photos')->assertExists('photo1.jpg');
Storage::disk('photos')->assertExists(['photo1.jpg', 'photo2.jpg']);
 
// Assert one or more files were not stored...
Storage::disk('photos')->assertMissing('missing.jpg');
Storage::disk('photos')->assertMissing(['missing.jpg', 'non-existing.jpg']);
 
// Assert that the number of files in a given directory matches the expected count...
Storage::disk('photos')->assertCount('/wallpapers', 2);
 
// Assert that a given directory is empty...
Storage::disk('photos')->assertDirectoryEmpty('/wallpapers');
});
<?php
 
namespace Tests\Feature;
 
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
 
class ExampleTest extends TestCase
{
public function test_albums_can_be_uploaded(): void
{
Storage::fake('photos');
 
$response = $this->json('POST', '/photos', [
UploadedFile::fake()->image('photo1.jpg'),
UploadedFile::fake()->image('photo2.jpg')
]);
 
// Assert one or more files were stored...
Storage::disk('photos')->assertExists('photo1.jpg');
Storage::disk('photos')->assertExists(['photo1.jpg', 'photo2.jpg']);
 
// Assert one or more files were not stored...
Storage::disk('photos')->assertMissing('missing.jpg');
Storage::disk('photos')->assertMissing(['missing.jpg', 'non-existing.jpg']);
 
// Assert that the number of files in a given directory matches the expected count...
Storage::disk('photos')->assertCount('/wallpapers', 2);
 
// Assert that a given directory is empty...
Storage::disk('photos')->assertDirectoryEmpty('/wallpapers');
}
}

預設情況下,fake 方法會刪除其暫存目錄中的所有檔案。如果您想要保留這些檔案,可以使用「persistentFake」方法。有關測試檔案上傳的更多資訊,您可以參考 HTTP 測試文件中關於檔案上傳的資訊

exclamation - Laravel 框架

image 方法需要 GD 擴充功能

自訂檔案系統

Laravel 的 Flysystem 整合開箱即用就支援數個「驅動程式」;但是,Flysystem 不僅限於這些,它還有許多其他儲存系統的轉接器。如果您想在 Laravel 應用程式中使用其中一個額外的轉接器,您可以建立自訂驅動程式。

為了定義自訂檔案系統,您需要一個 Flysystem 轉接器。讓我們將一個社群維護的 Dropbox 轉接器加入我們的專案中:

composer require spatie/flysystem-dropbox

接下來,您可以在應用程式的其中一個服務提供者boot 方法中註冊驅動程式。為此,您應該使用 Storage facade 的 extend 方法:

<?php
 
namespace App\Providers;
 
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\ServiceProvider;
use League\Flysystem\Filesystem;
use Spatie\Dropbox\Client as DropboxClient;
use Spatie\FlysystemDropbox\DropboxAdapter;
 
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
// ...
}
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Storage::extend('dropbox', function (Application $app, array $config) {
$adapter = new DropboxAdapter(new DropboxClient(
$config['authorization_token']
));
 
return new FilesystemAdapter(
new Filesystem($adapter, $config),
$adapter,
$config
);
});
}
}

extend 方法的第一個引數是驅動程式的名稱,第二個引數是一個閉包,它接收 $app$config 變數。該閉包必須回傳一個 Illuminate\Filesystem\FilesystemAdapter 的實例。$config 變數包含在 config/filesystems.php 中針對指定磁碟定義的值。

在您建立並註冊擴充功能的服務提供者後,您可以在 config/filesystems.php 設定檔中使用 dropbox 驅動程式。