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

 

posted @ 2017-10-13 16:13  丶老中医  阅读(2287)  评论(0编辑  收藏  举报
一切已经开始©2018 丶老中医