## 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上傳插件