## kartik-v/yii2-widget-fileinput 上传插件使用小结
使用Yii2开发项目的时候不免要用到文件上传,这里小结一下 [kartik-v/yii2-widget-fileinput](https://github.com/kartik-v/yii2-widget-fileinput) 插件的一些使用过程,以备查阅。
思路:图片上传使用统一的图片表关联存储图片在服务器上的相关信息,使用一个model子类渲染一个上传的视图,上传成功后利用回调函数将数据写入到隐藏域。
### 安装插件
这里使用**composer**命令安装 [kartik-v/yii2-widget-fileinput](https://github.com/kartik-v/yii2-widget-fileinput)。
```
composer require kartik-v/yii2-widget-fileinput "@dev"
```
### 模型
#### 图片模型
```
<?php
namespace backend\models;
use Yii;
use yii\db\ActiveRecord;
/**
* This is the model class for table "{{%images}}".
*
* @property integer $id
* @property string $url
* @property integer $create_time
* @property string $module
* @property integer $status
*/
class Images extends ActiveRecord
{
// public $imageFile;
/**
* @inheritdoc
*/
public static function tableName()
{
return '{{%images}}';
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['url', 'create_time', 'module'], 'required'],
[['created_at', 'status'], 'integer'],
[['url'], 'string', 'max' => 255],
[['module'], 'string', 'max' => 15],
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'url' => '图片路径',
'create_time' => '创建时间',
'module' => '模块',
'status' => '数据状态',
];
}
}
```
#### 上传模型
```
<?php
namespace backend\models;
use Yii;
use yii\base\Model;
/**
* 上传文件必须配置两个参数
*
* 1. 在 `/common/config/bootstrap.php` 文件中,配置`@uploadPath`的值,例如:`dirname(dirname(__DIR__)) . '/frontend/web/uploads'`
*
* 2. 在 `/backend/config/params.php` 文件中,配置`assetDomain`的值,例如:`http://localhost/yii2/advanced/frontend/web/uploads`
*
* Class UploadForm
* @package backend\models
*/
class UploadForm extends Model
{
public $imageFile;
public function rules()
{
return [
//数据验证这里可自己做
[['imageFile'], 'file', 'skipOnEmpty' => true, 'extensions' => 'png, jpg'],
];
}
public function upload()
{
if ($this->validate()) {
$path = Yii::getAlias('@uploadPath') . '/' . date("Ymd");
if (!is_dir($path) || !is_writable($path)) {
\yii\helpers\FileHelper::createDirectory($path, 0777, true);
}
$filePath = $path . '/' . Yii::$app->request->post('model', '') . '_' . md5(uniqid() . mt_rand(10000, 99999999)) . '.' . $this->imageFile->extension;
if ($this->imageFile->saveAs($filePath)) {
//这里将上传成功后的图片信息保存到数据库
$imageUrl = $this->parseImageUrl($filePath);
$imageModel = new Images();
$imageModel->url = $imageUrl;
$imageModel->created_at = time();
$imageModel->status = 0;
$imageModel->module = Yii::$app->request->post('model', '');
$imageModel->save(false);
$imageId = Yii::$app->db->getLastInsertID();
return ['imageUrl' => $imageUrl, 'imageId' => $imageId];
}
}
return false;
}
/**
* 这里在upload中定义了上传目录根目录别名,以及图片域名
* 将/var/www/html/advanced/frontend/web/uploads/20160626/file.png 转化为 http://statics.gushanxia.com/uploads/20160626/file.png
* format:http://domain/path/file.extension
* @param $filePath
* @return string
*/
private function parseImageUrl($filePath)
{
if (strpos($filePath, Yii::getAlias('@uploadPath')) !== false) {
return Yii::$app->params['assetDomain'] . str_replace(Yii::getAlias('@uploadPath'), '', $filePath);
} else {
return $filePath;
}
}
}
```
### 视图文件
```
<?php $form = ActiveForm::begin([
'options' => [
'class' => 'form-horizontal',
],
'fieldConfig' => [
// 'template' => "<div class='row'><div class='col-lg-1 text-right text-fixed'>{label}</div><div class='col-lg-9'>{input}</div><div class='col-lg-2 errors'>{error}</div></div>",
]
]); ?>
<?= $form->field($model, 'image_id')->hiddenInput()->label(false); ?>
<?= $form->field($upload, 'imageFile')->widget(\kartik\file\FileInput::className(), [
'options' => [
'accept' => 'images/*',
'module' => 'Goods',
'multipe' => false,
],
'pluginOptions' => [
// 异步上传的接口地址设置
'uploadUrl' => \yii\helpers\Url::to(['upload']),
'uploadAsync' => true,
// 异步上传需要携带的其他参数,比如商品id等,可选
'uploadExtraData' => [
'model' => 'goods'
],
// 需要预览的文件格式
'previewFileType' => 'image',
// 预览的文件
'initialPreview' => $p1 ?: '',
// 需要展示的图片设置,比如图片的宽度等
'initialPreviewConfig' => $p2 ?: '',
// 是否展示预览图
'initialPreviewAsData' => true,
// 最少上传的文件个数限制
'minFileCount' => 1,
// 最多上传的文件个数限制,需要配置`'multipe'=>true`才生效
'maxFileCount' => 10,
// 是否显示移除按钮,指input上面的移除按钮,非具体图片上的移除按钮
'showRemove' => false,
// 是否显示上传按钮,指input上面的上传按钮,非具体图片上的上传按钮
'showUpload' => true,
//是否显示[选择]按钮,指input上面的[选择]按钮,非具体图片上的上传按钮
'showBrowse' => true,
// 展示图片区域是否可点击选择多文件
'browseOnZoneClick' => true,
// 如果要设置具体图片上的移除、上传和展示按钮,需要设置该选项
'fileActionSettings' => [
// 设置具体图片的查看属性为false,默认为true
'showZoom' => true,
// 设置具体图片的上传属性为true,默认为true
'showUpload' => true,
// 设置具体图片的移除属性为true,默认为true
'showRemove' => true,
],
],
//网上很多地方都没详细说明回调触发事件,其实fileupload为上传成功后触发的,三个参数,主要是第二个,有formData,jqXHR以及response参数,上传成功后返回的ajax数据可以在response获取
'pluginEvents' => [
'fileuploaded' => "function (object,data){
$('.field-goods-name').show().find('input').val(data.response.imageId);
}",
//错误的冗余机制
'error' => "function (){
alert('图片上传失败');
}"
]
]); ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
```
### 控制器渲染页面效果
```
public function actionCreate()
{
$model = new Goods();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
'upload' => new UploadForm()
]);
}
}
/**
* Updates an existing Goods model.
* If update is successful, the browser will be redirected to the 'view' page.
* @param integer $id
* @return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
$upload = new UploadForm();
$relationImage = Images::find()->where(['id' => $model->name])->one();
$p1 = $p2 = [];
if ($relationImage) {
$p1 = $relationImage->url;
$p2 = [
'url' => Url::to(['delete']),
'key' => $relationImage->id,
];
}
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
'upload' => $upload,
'p1' => $p1,
'p2' => $p2,
]);
}
}
public function actionUpload()
{
$uploadForm = new UploadForm();
if(Yii::$app->request->isPost){
$uploadForm->imageFile = UploadedFile::getInstance($uploadForm, 'imageFile');
if($imageUrl = $uploadForm->upload()){
echo Json::encode([
'imageUrl' => $imageUrl,
'error' => '' //上传的error字段,如果没有错误就返回空字符串,否则返回错误信息,客户端会自动判定该字段来认定是否有错
]);
}else{
echo Json::encode([
'imageUrl' => '',
'error' => '文件上传失败'
]);
}
}
}
```
附上`goods`和`images`表结构:
```sql
CREATE TABLE `rotatain` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`image_id` int(11) NOT NULL COMMENT '图片id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE `images` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`url` varchar(255) NOT NULL COMMENT '图片路径',
`created_at` int(11) unsigned NOT NULL COMMENT '创建时间',
`module` char(15) NOT NULL COMMENT '模块',
`status` smallint(6) NOT NULL DEFAULT '0' COMMENT '数据状态',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCsaREMENT=1 DEFAULT CHARSET=utf8;
```
- 开始
- Yii2开发小技巧
- Yii2使用不同的方式进行邮件发送逻辑处理
- Yii2 Serialization of 'Closure' is not allowed 错误
- Yii创建应用
- Yii应用结构和流程
- Yii的路径别名
- Yii的请求
- Yii的响应
- Sessions 和 Cookies
- Yii自定义全局工具函数
- Yii2模型
- Yii2视图
- Yii2控制器
- 大数据节省内存处理
- 关联查询hasMany、hasOne
- Yii2 URL地址美化
- Yii2整合AdminLTE后台主题
- Yii2模型中的场景
- Yii2中的RBAC
- Yii2项目后台整合yii2-admin模块
- RBAC集成AdminLTE后台主题对菜单进行控制
- Yii2自定义Gii模板
- 修复AdminLTE引用外部字体文件导致访问变慢的情况
- Yii2事件简单使用
- Yii2模型事件
- Yii2使用GridView新增操作按钮
- Yii2向loyout模板文件中传值
- Yii2数据缓存
- Yii2缓存
- Yii2数据缓存之增删改查
- Yii2拓展
- Yii2日期时间插件-datetimepicker
- kartik-v/yii2-widget-fileinput上传插件