目录搜索
阅读前篇简介Yii 是什么从 Yii 1.1 升级入门安装 Yii运行应用第一次问候使用Forms数据库应用使用 Gii 生成代码进阶应用结构概述入口脚本应用(Applications)应用组件(Application Components)控制器(Controllers)模型(Models)视图(views)模块(Modules)过滤器(Filters)小部件(Widgets)前端资源(Assets)扩展(Extensions)请求处理运行概述启动引导(Bootstrapping)路由和创建URL请求(Requests)响应(Responses)Sessions 和 Cookies错误处理(Handling Errors)日志(Logging)关键概念组件(Component)属性(Property)事件(Events)行为(Behaviors)配置(Configurations)别名(Aliases)类自动加载(Autoloading)服务定位器(Service Locator)依赖注入容器(Dependency Injection Container)配合数据库工作数据库访问 (Data Access Objects)查询生成器(Query Builder)活动记录(Active Record)数据库迁移(Migrations)SphinxRedisMongoDBElasticsearch接收用户数据创建表单(Creating Forms)输入验证(Validating Input)文件上传(Uploading Files)收集列表输入(Collecting Tabular Input)多模型的复合表单(Getting Data for Multiple Models)显示数据格式化输出数据(Data Formatting)分页(Pagination)排序(Sorting)数据提供器(Data Providers)数据小部件(Data Widgets)客户端脚本使用(Working with Client Scripts)主题(Theming)安全认证(Authentication)授权(Authorization)处理密码(Working with Passwords)客户端认证(Auth Clients)最佳安全实践(Best Practices)缓存概述数据缓存片段缓存页面缓存HTTP 缓存RESTfull Web服务快速入门(Quick Start)资源(Resources)控制器(Controllers)路由(Routing)格式化响应(Response Formatting)授权认证(Authentication)速率限制(Rate Limiting)版本(Versioning)错误处理(Error Handling)开发工具调试工具栏和调试器使用Gii生成代码生成API文档测试概述(Overview)配置测试环境(Testing environment setup)单元测试(Unit Tests)功能测试(Function Tests)验收测试(Acceptance Tests)测试夹具(Fixtures)高级专题高级应用模板创建自定义应用程序结构控制台命令核心验证器(Core Validators)国际化收发邮件性能优化共享主机环境模板引擎集成第三方代码小部件Bootstrap 小部件Jquery UI助手类概述Array 助手(ArrayHelper)Html 助手(Html)Url 助手(Url)
文字

文件上传

文件上传

在Yii里上传文件通常使用yii\web\UploadedFile类, 它把每个上传的文件封装成 UploadedFile 对象。 结合yii\widgets\ActiveForm和models,你可以轻松实现安全的上传文件机制。

创建模型

和普通的文本输入框类似,当要上传一个文件时,你需要创建一个模型类并且用其中的某个属性来接收上传的文件实例。 你还需要声明一条验证规则以验证上传的文件。 举例来讲,

namespace app\models;

use yii\base\Model;
use yii\web\UploadedFile;

class UploadForm extends Model{
    
    public $imageFile;

    public function rules()
    {
        return [
            [['imageFile'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
        ];
    }
    
    public function upload()
    {
        if ($this->validate()) {
            $this->imageFile->saveAs('uploads/' . $this->imageFile->baseName . '.' . $this->imageFile->extension);
            return true;
        } else {
            return false;
        }
    }
}

在以上代码里,imageFile 属性用于接收上传的文件实例。它对应一条file 验证规则, 该规则使用 yii\validators\FileValidator 来确保只上传扩展名为 png 或 jpg 的文件。 upload() 方法会执行该验证并且把上传的文件保存在服务器上。

通过 file 验证器,你可以检查文件的扩展名,大小,MIME类型等等。详情请查阅 Core Validatators 章节。

>提示: 如果你要上传的是一张图片,可以考虑使用image验证器。 image 验证器是通过yii\validators\ImageValidator实现验证的,确保对应的模型属性 收到的文件是有效的图片文件,然后才保存,或者使用扩展类Imagine Extension进行处理.

渲染文件输入

接下来,在视图里创建一个文件输入控件

<?phpuse yii\widgets\ActiveForm;
?>

<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>

    <?= $form->field($model, 'imageFile')->fileInput() ?>

    <button>Submit</button>

<?php ActiveForm::end() ?>

需要注意的是要记得在表单选项里加入 enctype 属性以确保文件能被正常上传。 fileInput() 方法会渲染一个 <input type="file">标签,让用户可以选择一个文件上传。

视图和模型的连接

现在,在控制器方法里编写连接模型和视图的代码以实现文件上传。

namespace app\controllers;

use Yii;
use yii\web\Controller;
use app\models\UploadForm;
use yii\web\UploadedFile;

class SiteController extends Controller{
    public function actionUpload()
    {
        $model = new UploadForm();

        if (Yii::$app->request->isPost) {
            $model->imageFile = UploadedFile::getInstance($model, 'imageFile');
            if ($model->upload()) {
                // 文件上传成功
                return;
            }
        }

        return $this->render('upload', ['model' => $model]);
    }
}

在上面的代码里,当提交表单的时候,yii\web\UploadedFile::getInstance()方法就被调用, 上传的文件用一个 UploadedFile 实例表示。然后,我们依靠模型的验证规则确保上传的文件是有效的, 并将文件保存在服务器上。

上传多个文件

将前面所述的代码做一些调整,也可以一次性上传多个文件。

首先你得调整模型类,在 file 验证规则里增加一个 maxFiles 选项,用以限制一次上传文件的最大数量。 upload()方法也得修改, 以便一个一个地保存上传的文件。

namespace app\models;

use yii\base\Model;
use yii\web\UploadedFile;

class UploadForm extends Model{
    
    public $imageFiles;

    public function rules()
    {
        return [
            [['imageFiles'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg', 'maxFiles' => 4],
        ];
    }
    
    public function upload()
    {
        if ($this->validate()) { 
            foreach ($this->imageFiles as $file) {
                $file->saveAs('uploads/' . $file->baseName . '.' . $file->extension);
            }
            return true;
        } else {
            return false;
        }
    }
}

在视图文件里,你需要把 multiple 选项添加到fileInput()函数调用里, 这样文件输入控件就可以接收多个文件。

<?phpuse yii\widgets\ActiveForm;
?>

<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>

    <?= $form->field($model, 'imageFiles[]')->fileInput(['multiple' => true, 'accept' => 'image
    public $filename;

   
    public $key;

   
    protected $fileObject// SplFileObject is very convenient for seeking to particular line in a file


   
    public function init()
   
{
        parent::init();

        // open file
        $this->fileObject = new SplFileObject($this->filename);
    }

   
    protected function prepareModels()
   
{
        $models = [];
        $pagination = $this->getPagination();

        if ($pagination === false) {
            // in case there's no pagination, read all lines
            while (!$this->fileObject->eof()) {
                $models[] = $this->fileObject->fgetcsv();
                $this->fileObject->next();
            }
        } else {
            // in case there's pagination, read only a single page
            $pagination->totalCount = $this->getTotalCount();
            $this->fileObject->seek($pagination->getOffset());
            $limit = $pagination->getLimit();

            for ($count = 0$count < $limit; ++$count) {
                $models[] = $this->fileObject->fgetcsv();
                $this->fileObject->next();
            }
        }

        return $models;
    }

   
    protected function prepareKeys($models)
   
{
        if ($this->key !== null) {
            $keys = [];

            foreach ($models as $model) {
                if (is_string($this->key)) {
                    $keys[] = $model[$this->key];
                } else {
                    $keys[] = call_user_func($this->key, $model);
                }
            }

            return $keys;
        } else {
            return array_keys($models);
        }
    }

   
    protected function prepareTotalCount()
   
{
        $count = 0;

        while (!$this->fileObject->eof()) {
            $this->fileObject->next();
            ++$count;
        }

        return $count;
    }
}
上一篇:下一篇: