laravel5.5 文件上傳說明 文件上傳的單元測試寫法


laravel5.5 文件上傳

 1、獲取上傳的文件

可以使用 Illuminate\Http\Request 實例提供的 file 方法或者動態屬性來訪問上傳文件, file 方法返回 Illuminate\Http\UploadedFile 類的一個實例,該類繼承自 PHP 標准庫中提供與文件交互方法的 SplFileInfo 類:

$file = $request->file('photo');
$file = $request->photo;

你可以使用 hasFile 方法判斷文件在請求中是否存在:

if ($request->hasFile('photo')) {
    //文件存在...
}

SplFileInfo類:

<?php

$file = new SplFileInfo('test.jpg');
 
print_r(array(
    'getATime' => $file->getATime(), //最后訪問時間
    'getBasename' => $file->getBasename(), //獲取無路徑的basename
    'getCTime' => $file->getCTime(), //獲取inode修改時間
    'getExtension' => $file->getExtension(), //文件擴展名
    'getFilename' => $file->getFilename(), //獲取文件名
    'getGroup' => $file->getGroup(), //獲取文件組
    'getInode' => $file->getInode(), //獲取文件inode
    'getLinkTarget' => $file->getLinkTarget(), //獲取文件鏈接目標文件
    'getMTime' => $file->getMTime(), //獲取最后修改時間
    'getOwner' => $file->getOwner(), //文件擁有者
    'getPath' => $file->getPath(), //不帶文件名的文件路徑
    'getPathInfo' => $file->getPathInfo(), //上級路徑的SplFileInfo對象
    'getPathname' => $file->getPathname(), //全路徑
    'getPerms' => $file->getPerms(), //文件權限
    'getRealPath' => $file->getRealPath(), //文件絕對路徑
    'getSize' => $file->getSize(),//文件大小,單位字節
    'getType' => $file->getType(),//文件類型 file  dir  link
    'isDir' => $file->isDir(), //是否是目錄
    'isFile' => $file->isFile(), //是否是文件
    'isLink' => $file->isLink(), //是否是快捷鏈接
    'isExecutable' => $file->isExecutable(), //是否可執行
    'isReadable' => $file->isReadable(), //是否可讀
    'isWritable' => $file->isWritable(), //是否可寫
));

2、驗證文件是否上傳成功

使用 isValid 方法判斷文件在上傳過程中是否出錯:

if ($request->file('photo')->isValid()){
    //上傳成功...
}

3、獲取文件的路徑 & 擴展名 & 其他

UploadedFile 類還提供了訪問上傳文件絕對路徑和擴展名的方法。 extension 方法可以基於文件內容判斷文件擴展名,該擴展名可能會和客戶端提供的擴展名不一致:

$path = $request->photo->path();
$extension = $request->photo->extension();

其他文件方法

$file->guessExtension() //根據mime類型返回擴展名。return  string | null
$file->getMimeType() //返回文件的mime類型。return string | null
$file->move(string $directory, string $name = null) //將文件移動到一個新的位置。return File
$file->getClientOriginalName() //返回原始的文件名。return string | null
$file->getClientOriginalExtension() //返回原始文件擴展名。 return string
$file->getClientMimeType() //返回文件mime類型。return string | null
$file->guessClientExtension() //根據客戶端mime類型返回擴展。return string | null
$file->getClientSize() //返回文件的大小字節。return int | null
$file->getError() //返回上傳文件的錯誤。return int
$file->isValid() //返回文件是否成功上傳。return bool
$file->getMaxFilesize() //返回在php.ini中配置的上傳文件的最大大小。return static int
$file->getErrorMessage() //返回一個包含信息的上傳錯誤信息。return string

 

UploadedFile 實例上還有很多其他可用方法,查看該類的API文檔了解更多信息。

4、保存上傳的文件

要保存上傳的文件,需要使用你所配置的某個文件系統,對應配置位於 config/filesystems.php

'disks' => [

        'local' => [
            'driver' => 'local',
            'root' => storage_path('app'),
        ],

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

        's3' => [
            'driver' => 's3',
            'key' => env('AWS_KEY'),
            'secret' => env('AWS_SECRET'),
            'region' => env('AWS_REGION'),
            'bucket' => env('AWS_BUCKET'),
        ],

    ],

Laravel 默認使用 local 配置存放上傳文件,即本地文件系統,默認根目錄是 storage/apppublic 也是本地文件系統,只不過存放在這里的文件可以被公開訪問,其對應的根目錄是 storage/app/public,要讓 Web 用戶訪問到該目錄下存放文件的前提是在應用入口 public 目錄下建一個軟鏈 storage 鏈接到 storage/app/public

建立軟連接命令:

php artisan storage:link

在你的 public 目錄下就會有一個 link 軟連接指向了storage/app/public 目錄:

public/storage(軟連接) → storage/app/public

目錄樹結構是這樣的:

public/
├── storage(軟連接,指向目錄 `storage/app/public`)
├── css/
│   └── bootstrap.css
└── js/
    └── bootstrap.js

storage/
└── app/
    └── public/
        └── user-avatar.png

那么為何要創建軟連接呢?

項目根目錄下的 public 是一個特殊的目錄——存放可公共訪問的資源。就像你看到的,除了 storage 這個軟鏈接,還有 CSSJS 文件都放在這里。如果你的域名是 my.app,那么訪問這些資源的 URL 如下:

  • http://my.app/storage/user-avatar.png
  • http://my.app/css/bootstrap.css
  • http://my.app/js/bootstrap.js

提示:你會發現,http://my.app/storage/user-avatar.png 實際訪問的文件資源的服務器地址是 storage/app/public/user-avatar.png

如果上傳的資源文件是存儲在本地的,Laravel 默認會放在 storage/app 里面,這個目錄是不可見的,如果想要能公共訪問就必須暴露在項目根目錄下的 public 中,這就是創建軟鏈接的原因 。

 

UploadedFile 類有一個 store 方法,該方法會將上傳文件移動到相應的磁盤路徑上,該路徑可以是本地文件系統的某個位置,也可以是雲存儲(如Amazon S3)上的路徑。

  • store 方法接收一個文件保存的相對路徑(相對於文件系統配置的根目錄 ),該路徑不需要包含文件名,因為系統會自動生成一個唯一ID作為文件名。
  • store 方法還接收一個可選的參數 —— 用於存儲文件的磁盤名稱作為第二個參數(對應文件系統配置 disks 的鍵名,默認值是 local),該方法會返回相對於根目錄的文件路徑:
$path = $request->photo->store('images');
$path = $request->photo->store('images', 'public');

如果你不想自動生成文件名,可以使用 storeAs 方法,該方法接收保存路徑、文件名和磁盤名作為參數:

$path = $request->photo->storeAs('images', 'filename.jpg');
$path = $request->photo->storeAs('images', 'filename.jpg', 'public');

那么目錄結構是這樣的:

storage/
└── app/
    └── public/
        └── images/
            └── filename.jpg

下面給出一個參考的實例:

route:

Route::post('fileupload', 'UploadController@fileUpload');

UploadController.php:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;

class UploadController extends Controller
{
    /**
     * 接受一個上傳的圖片
     *
     * @param  file photo
     * @return \Illuminate\Http\Response
     */
    public function fileUpload(Request $request)
    {
          if($request->hasFile('photo') && $request->file('photo')->isValid()){
            //獲取上傳的文件
            $file = $request->file('photo');
            $name = $file->getClientOriginalName();
            if($store_result = $file->storeAs('images', $name, 'public')){
                return response()->json(['success' => 'true'], 200);
            }
     }
} 

再寫一個單元測試實例:

生成一個測試文件

php artisan make:test UploadTest

修改測試文件 tests/Feature/UploadTest.php 內容:

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

class UploadTest extends TestCase
{
    /** @test */
    public function it_can_upload_a_image()
    {
        $fake_image = UploadedFile::fake()->image('temp_test.jpg');

        $response = $this->json('POST', "/fileupload", ['photo' => $fake_image]);
        // 斷言該文件被存儲
        Storage::disk('public')->assertExists('images/test.jpg'); 
    }
}

運行測試:

phpunit --filter UploadTest

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM