abei1982 2017-06-06 14:23:49 6027次浏览 2条回复 8 2 0

很多新人对上传这种操作有些害怕、摸不着头脑,今天阿北带你学习一边yii2 UploadFile类,看看yii2如何帮你轻松的完成上传操作。

老样子,先来个目录

  • 初步熟悉 UploadedFile 类
  • 从 Model 开始的上传
  • 没有 Model 的上传

UploadedFile 类

UploadedFile 类位于 vendor/yiisoft/yii2/web/UploadedFile.php

它提供了比如 getInstancegetInstancesgetInstanceByNamesaveAs等诸多方法 详情可以参考速查表 http://nai8.me/tool-sc.html#section-23

从Model开始的上传

我们先来设计一个简单的会员表,实现对其头像的上传功能。

Snip20170606_12副本.jpg

然后我们新建一个action并写下如下代码。

// @app/FileController.php
public function actionIndex(){
    $model = User::findOne(1);
    if(Yii::$app->request->isPost){
        $file = UploadedFile::getInstance($model,'avatar');
        var_dump($file);
    }

    return $this->render('index',[
        'model'=>$model
    ]);
    // 视图里代码 <?= $form->field($model,'avatar')->fileInput();?>
}

其实 UploadedFile 只是对上传文件信息的再次封装并提供一组用于操作该文件的方法,就像上面代码一样,我们将对 UploadedFile 获取的上传对象进行打印,看看它到底是什么?

在这里我们使用 yii2-debug 来观察这一切。

Snip20170606_17.png

而通过 UploadedFile::getInstance 接收后形成的对象 $file 如下图:

Snip20170606_16.png

在这里你看到了,对于 UploadedFile 对象,它的属性和上传文件的信息一致,我们暂时认为 $file = 上传文件 + 一些方法,并且它可以像正常 Model 接收数据一样获取上传的文件。

既然我们已经得到了文件,它就在 $file,那么现在我们将它保存到指定的目录就好了。

这要用到 UploadedFile 提供的 saveAs 方法,当然在这里你也可以用 getExtension 获取文件扩展名等等。

但是要注意,此刻我们操作的是一个具体的对象,saveAs 是保存这个文件、getExtension 是获得此文件的扩展名,这些都是对象方法,不是静态方法,初学者自行体会。

// 继续编写actionIndex
...
if(Yii::$app->request->isPost){
    $file = UploadedFile::getInstance($model,'avatar');
    $path = 'data/'.time().".".$file->getExtension();
    if($file->saveAs(Yii::getAlias("@webroot").'/'.$path) === true){
        $model->avatar = $path;
    }
    $model->update();
}
...

要注意的是,saveAs 的参数是一个服务器物理路径。

执行后,我数据库中已经有了该头像的相对路径。

Snip20170606_18.png

当然这是最简单的,你也可以通过 Model 的 rulesaction自己的逻辑实现对文件的验证,比如扩展名、比如大小、比如等等。

这一切貌似很轻松就完成了,我们不再用去处理蹩脚的原生PHP上传文件,但是有几种特殊情况还需要说下。

如何一下上传并接受多个文件

比如我的 user 增加了一列 identity_card,代表身份证,我现在要用来存放身份证的正反面图片

按照上面的需求,视图肯定是要变动下,将identity_card变为一个数组

<?= $form->field($model,'identity_card[]')->fileInput();?>
<?= $form->field($model,'identity_card[]')->fileInput();?>

然后我们使用 UploadedFile::getInstances 来完成,核心代码如下:

...
if(Yii::$app->request->isPost){
    $files = UploadedFile::getInstances($model,'identity_card'); // 不是identity_card[]
    var_dump($files);
}
...

getInstances 能帮我们接收一个数组类型的 fileInput,看看结果

Snip20170606_19.png

然后我们可以对这个 $files 结果集进行遍历等操作,据具体场景而定即可。

没有 Model 的上传

上面都是通过一个模型来接收客户传递过来的文件,它很方便,我们接下来介绍下 jie'sho 不通过 Model 如何去处理一个文件或一组文件上传接收问题。

在这里我不计划写任何代码,给大家一个图,也许明白的够透彻。

Snip20170606_20.png

话说其实 getInstanceByNamegetInstancesByName 才是 UploadedFile 真正核心的函数, getInstancegetInstances 最后也是调用了它们。

现在你会了么?接收一个或一组文件。

还有些小细节

getBaseName()

该函数能获取上传文件的原始名,需要注意的是返回的名字不包含扩展名。

getExtension()

该函数可以获取上传文件的扩展名,比如一个文件为a.png,则该函数返回的是png而不是image/png,另外扩展名均处理为小写了已经。

几个变量

另外如果我们也可以直接调用一些变量

  • type 返回比如image/png这样的媒体类型
  • size 返回文件的大小
  • name 文件原始名(含扩展名)
  • tempName 系统存放文件的临时名

以上就是 UploadedFile 的所有用法和一些变量,希望对你有用。

更多yii2干货欢迎来我的小站 http://nai8.me

觉得很赞
  • 回复于 2017-06-23 21:12 举报

    我用 UploadedFile 可以获取到视图传上来的图片 但是在开发 api 上传的时候就获取不到 看了下$_FILES 上过来的格式不一样 就是说 $_FILES 不一样?请问有什么解决办法嘛?我现在用的是原生的上传方法

    1 条回复
    回复于 2018-11-05 18:12 回复

    <input type="file" name="模型名[字段名][]">
    这样改一下就可以了,你可以先照着官方文档的去写,页面看一下源码你就明白了。这里模型名是因为按照官方ActiveForm 去写的时候需要给页面一个 model,字段名还是你之前的就行,和 UploadedFile::getInstances($model, '字段名') 这里对应就可以了。

  • 回复于 2017-07-06 09:28 举报

    mark,以后用到

您需要登录后才可以回复。登录 | 立即注册