yii 集成plupload

本文介绍了一个自定义的Yii2表单组件,实现了水平布局,并详细讲解了如何使用该组件进行文件上传,包括单文件和多文件上传的实现方式,以及上传后的图片显示和删除操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先需要重写表单,继承ActiveForm

namespace common\widgets;

use Yii;
use yii\helpers\Html;
use yii\base\InvalidConfigException;

class HorizontalActiveForm extends \yii\widgets\ActiveForm
{
    /**
     * @var string the default field class name when calling [[field()]] to create a new field.
     * @see fieldConfig
     */
    
    /**
     * @var array HTML attributes for the form tag. Default is `[]`.
     */
    public $options = [];

    /**
     * @var string the form layout. Either 'default', 'horizontal' or 'inline'.
     * By choosing a layout, an appropriate default field configuration is applied. This will
     * render the form fields with slightly different markup for each layout. You can
     * override these defaults through [[fieldConfig]].
     * @see \yii\bootstrap\ActiveField for details on Bootstrap 3 field configuration
     */
    public $layout = 'horizontal';


    /**
     * {@inheritdoc}
     */
    public function init()
    {
        if (!in_array($this->layout, ['default', 'horizontal', 'inline'])) {
            throw new InvalidConfigException('Invalid layout type: ' . $this->layout);
        }

        if ($this->layout !== 'default') {
            Html::addCssClass($this->options, 'row form-' . $this->layout);
        }
 
        $this->fieldConfig = [
            'template' => "<div class='row row-box'>
                            <div class='col-xs-2 col-sm-2 text-right'>
                                {label}
                            </div>
                            <div class='col-xs-9 col-sm-9'>
                                {input}
                                <div class='help-block'>{hint}</div>
                                <div class='help-block'>{error}</div>
                            </div>
                        </div>",
        ];
        parent::init();
    }

    /**
     * {@inheritdoc}
     * @return ActiveField the created ActiveField object
     */
    public function field($model, $attribute, $options = [])
    {
        $hidden = '';
        if(isset($options['options']['hidden'])) {
            $hidden = ' hide';
        }
        if(isset($options['options']['whole_row'])) {
            $options = [
                'options' => ['class' => 'col-md-12 col-sm-12 whole-row form-group' . $hidden],
                'template' => "<div class='row row-box'>
                            <div class='col-xs-1 col-sm-1 text-right'>
                                {label}
                            </div>
                            <div class='col-xs-10 col-sm-10'>
                                {input}
                                <div class='help-block'>{hint}</div>
                                <div class='help-block'>{error}</div>
                            </div>
                        </div>",
            ];
        } else if(isset($options['options']['media_field'])) {
            $data = " data-id='". $attribute ."' ";
            $data .= " id='".$attribute."_uploader' ";
            if(isset($options['options']['multi_selection'])) {
                $data .= " data-multiple='multiple' ";
            }
            if(isset($options['options']['save_path'])) {
                $data .= " data-oss-path='". $options['options']['save_path']."' ";
            }
            $media_list = '';
            if(isset($options['options']['attachment'])) {
                $attachment = $options['options']['attachment'];
                if(!empty($attachment)) {
                    $media_list = '<li><div class="img-info"><img src="/' . $attachment . '" /><p data-id="' .$model->id. '"></p><div class="delete-image"> X </div></div></li>';
                }
            }
            $options = [
                'options' => ['class' => 'col-md-12 col-sm-12 whole-row form-group' . $hidden],
                'template' => "<div class='row row-box'>
                    <div class='col-xs-1 col-sm-1 text-right'>
                        {label}
                    </div>
                    <div class='col-xs-10 col-sm-10'>
                        <div class='media-picker'>
                            <a class='media-picker-button' ".$data." href='javascript:void(0)'>
                                <span class='fa fa-cloud-upload'></span>
                            </a>
                            {input}
                            <div class='help-block'>{hint}</div>
                            <div class='help-block'>{error}</div>
                            <div class='media-list'>
                            <ul>". $media_list ."</ul>
                            </div>
                        </div>
                    </div>
                </div>",
            ];
        } else {
            $options = [
                'options' => ['class' => 'col-md-6 col-sm-12 double-row form-group' . $hidden]
            ];
        }
        return parent::field($model, $attribute, $options);
    }
}

这里只考虑了单个文件,多个文件循环显示就好,如果是直接存在当前表中,则更简单,只需要$model->image就行,不需要再传入attachment

使用

<?php $form = HorizontalActiveForm::begin(); ?>

    <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>

    <?= $form->field($model, 'attachment_id', [
        'options' =>  [
            'media_field' => true, 
            'save_path' => 'common', 
            //'multi_selection' => true,  // 多文件上传使用
            'attachment' => empty($model->attachment) ? '' : $model->attachment->url
            ]
        ])->hiddenInput()->hint('单图上传,格式:png,jpg,jpeg,gif') ?>

    <?= $form->field($model, 'describe', ['options' =>  ['whole_row' => true]])->textarea(['rows' => 6]) ?>

    <?= RightSubmitButton::widget() ?>

    <?php HorizontalActiveForm::end(); ?>

上传图片

namespace backend\controllers;

use Yii;
use yii\web\Controller;
use common\models\attachment\Attachment;
use yii\web\UploadedFile;

class UploaderController extends Controller {
    public $enableCsrfValidation = false;

    public function actionUploader() {
        $updir = Yii::$app->request->post('updir');
        $files = UploadedFile::getInstanceByName('ysx_media');
        $savePath = $this->getDir($updir);
        $ext = $files->getExtension();
        $type = 1;
        $cover_url = '';
        if(in_array($ext, ['mp4', '3gp'])) {
            $type = 2;
        } else if(in_array($ext, ['mp3', '0gg'])) {
            $type = 4;
        }
        $saveName = $this->getName($ext);
        $result = $savePath . '/' . $saveName;

        $isSave = $files->saveAs($result);
        if($isSave) {
            $attachementModel = new Attachment();
            $attachementModel->name = $saveName;
            $attachementModel->url = $result;
            $attachementModel->save();
            $data = [
                'error' => 0,
                'attachement_id' => $attachementModel->id,
                'url' => $result
            ];
        } else {
            $data = [
                'error' => 1,
                'msg' => '上传失败!'
            ];
        }
        return json_encode($data);
    }

    public function actionDeluploader() {
        $attachement_id = Yii::$app->request->post('attachement_id');
        $attachementModel = Attachment::findOne($attachement_id);
        @unlink($attachementModel->url);
        $attachementModel->delete();
        $data = [
            'error' => 0,
            'msg' => '删除成功!'
        ];
    }

    /**
     * 获取上传目录
     */
    private function getDir($dir) {
        $baseDir = "uploads/";
        if(!empty($dir)) {
            $baseDir = $baseDir . $dir;
            if(!file_exists($baseDir)) {
                @mkdir($baseDir, 777);
            }
        }
        return $baseDir;
    }

    /**
     * 重命名
     */
    private function getName($ext) {
        $str = time() . rand(1000, 99999);
        return $str . '.' . $ext;
    }
}

js

gObjectName = ''
gObjectAttachements = new Array() //多图片上传id
gObjectNames = new Array() //多图片上传保持
videoAttachmentId = ''; // 由于需要单独上传视频封面,这里保存下视频id
currentUrl = window.location.href;
baseBackend = window.location.protocol + "//" +window.location.host;
ossUrl = 'http://oss.yishixue.com/';

$(document).ready(function() {
    //上传
    $('.media-picker').each(function() {
        var el = $(this);
        var elbtn = el.find('.media-picker-button');
        var multiSelection = false;
        // 上传目录
        var inputField = el.find('input[type=hidden]');
        var token = $('input[name="_csrf-backend"]').val();
        // 视频封面,需要获取attachment_id
        var attachementId = '';
        
        // 类型
        var mediaType = elbtn.attr('data-type');
        var mimeTypes = [ 
            { title: "Image files", extensions: "jpg,jpeg,gif,png,bmp" },
            { title: "Video files", extensions: "mp4,3gp" },
            { title: "Video files", extensions: "pdf,doc,docx,ppt,pptx,xls,xlsx,zip,rar" }
        ];
        if(mediaType == 'video') {
            mimeTypes = [ 
                { title: "Video files", extensions: "mp4,3gp" }
            ];
        } else if(mediaType == 'file') {
            mimeTypes = [ 
                { title: "Video files", extensions: "pdf,doc,docx,ppt,pptx,xls,xlsx,zip,rar" }
            ]; 
        } else if(mediaType == 'image') {
            mimeTypes = [ 
                { title: "Image files", extensions: "jpg,jpeg,gif,png,bmp" }
            ]; 
        }
 
        // 是否多文件上传
        if (elbtn.attr('data-multiple') == 'multiple') {
            multiSelection = true;
            // 如果已经有文件
            var oldFiles = inputField.val();
            if (oldFiles != '') {
                var oldFilesArr = $.parseJSON(oldFiles);
                for (var x = 0; x < oldFilesArr.length; x++) {
                    gObjectNames.push(oldFilesArr[x]);
                }
            }
        }
 
        var updir = elbtn.attr('data-oss-path');
        var uploader = new plupload.Uploader({
            runtimes: 'html5,flash,silverlight,html4',
            browse_button: elbtn.attr('data-id') + '_uploader',
            url: baseBackend + '/uploader/uploader',
            file_data_name: 'ysx_media',
            multi_selection: multiSelection,
            auto_start: true,
            flash_swf_url: '../plupload/js/Moxie.swf',
            silverlight_xap_url: '../plupload/js/Moxie.xap',
            
            //只允许上传图片和zip,rar文件
            
            filters: {
                mime_types: mimeTypes,
                max_file_size: '50mb', //最大只能上传10mb的文件
                prevent_duplicates: false //不允许选取重复文件
            },
 
            init: {
                PostInit: function() {
                    gObjectAttachements = new Array() //多图片上传id
                    gObjectNames = new Array() //多图片上传保持
                },
                FilesAdded: function(up) {
                    var videoCover = el.parents('.form-video-cover');
                    if(videoCover != undefined) {
                        attachementId = videoAttachmentId;
                    }
                    uploader.setOption("multipart_params", {"updir": updir, "_token": token, "attachement_id":attachementId});
                    up.start(); //选择完后直接上传
                },
 
                FileUploaded: function(up, file, info) {
                    if (info.status == 200) {
                        var fileType = file.type;
                        var isImage = fileType.indexOf('image');
                        var isVideo = fileType.indexOf('video');
                        var isApplication = fileType.indexOf('application');

                        // 获取返回德数据
                        var fileInfos = $.parseJSON(info.response);
                        if(fileInfos.error == 0) {
                            var fileAttachementId = fileInfos.attachement_id
                            var fileUrl = fileInfos.url;
                            if (multiSelection) {
                                // 多文件转为json
                                gObjectAttachements.push(fileAttachementId);
                                inputField.val(JSON.stringify(gObjectAttachements));
                                
                                // 把图片显示出来
                                gObjectNames.push(fileUrl);
                                var imageHtml = '';
                                for (var i = 0; i < gObjectNames.length; i++) {
                                    if (isImage > -1) {
                                        imageHtml += '<li class="image-info"><div class="info"><img src="' +  gObjectNames[i] + '"/><p data-id="' + gObjectAttachements[i] + '">' + gObjectNames[i] + '</p><div class="delete-image"> X </div></div></li>';
                                    }
                                    if (isVideo > -1) {
                                        imageHtml += '<li class="video-info"><div class="info"><video controls src="' +  gObjectNames[i] + '"></video><p data-id="' + gObjectAttachements[i] + '">' + gObjectNames[i] + '</p><div class="delete-image"> X </div></div></li>';
                                    } 
                                    if (isApplication > -1) {
                                        imageHtml += '<li class="file-info"><div class="info"><div class="attachment-file">' +  gObjectNames[i] + '</div><p data-id="' + gObjectAttachements[i] + '">' + gObjectNames[i] + '</p><div class="delete-image"> X </div></div></li>';
                                    }
                                }
                                el.find('.media-list ul').html(imageHtml);
     
                            } else {
                                // 单文件直接用名称, 
                                inputField.val(fileAttachementId);
                                gObjectName = fileUrl
                                    // 把图片显示出来
                                var imageHtml = '';
                                if (isImage > -1) {
                                    imageHtml = '<li class="image-info"><div class="info"><img src="' +  gObjectName + '"/><p data-id="' + fileAttachementId + '">' + gObjectName + '</p><div class="delete-image"> X </div></div></li>';
                                }
                                if (isVideo > -1) {
                                    imageHtml = '<li class="video-info"><div class="info"><video controls src="' +  gObjectName + '"></video><p data-id="' + fileAttachementId + '">' + gObjectName + '</p><div class="delete-image"> X </div></div></li>';
                                }
                                if (isApplication > -1) {
                                    imageHtml += '<li class="file-info"><div class="info"><div class="attachment-file">' +  gObjectName + '</div><p data-id="' + fileAttachementId + '">' + gObjectName + '</p><div class="delete-image"> X </div></div></li>';
                                }

                                // 视频不让多选
                                if (isVideo > -1) {
                                     // 封面
                                     coverDom = el.parents('.form-video').find('.form-video-cover');
                                     if(coverDom.hasClass('hide')) {
                                        coverDom.removeClass('hide');
                                     }
                                     videoAttachmentId = fileAttachementId;
                                }
                                el.find('.media-list ul').html(imageHtml);
                            }
                        } else {
                            alert(fileInfos.msg);
                        }
                    } else {
                        alert(info.response);
                    }
                },
 
                Error: function(up, err) {
                    if (err.code == -600) {
                        alert("\n选择的文件太大了,可以根据应用情况,在upload.js 设置一下上传的最大大小");
                    } else if (err.code == -601) {
                        alert("\n选择的文件后缀不对,可以根据应用情况,在upload.js进行设置可允许的上传文件类型");
                    } else if (err.code == -602) {
                        alert("\n这个文件已经上传过一遍了");
                    } else {
                        alert("\nError xml:" + err.response);
                    }
                }
            }
        })
        uploader.init();
    })
 
    // 删除
    $('.media-picker').each(function() {
        var el = $(this)
        var inputField = el.find('input[type=hidden]');
        var fileAttachement = inputField.val();
        var elbtn = el.find('.media-picker-button');
        var multiSelection = false;
        // 是否多文件上传
        if (elbtn.attr('data-multiple') == 'multiple') {
            multiSelection = true;
        }
        if (multiSelection) {
            el.on('click', '.delete-image', function() {
                var elDel = $(this);
                // 得到filename
                var currentFileName = elDel.prev('p').html();
                // 得到id
                var currentAttachementId = elDel.prev('p').attr('data-id');
                // 删除当前的父级li
                elDel.parent().parent().remove();
                // 重新赋值数组
                // 去掉url数组中的当前url
                for(var i in gObjectNames) {
                    if(gObjectNames[i] == currentFileName) {
                        gObjectNames.splice(i,1);
                       break;
                    }
                }
                // 去掉id数组中的当前id
                for(var i in gObjectAttachements) {
                    if(gObjectAttachements[i] == currentAttachementId) {
                        gObjectAttachements.splice(i,1);
                        break;
                    }
                }
                // 后端不做删除
                /*$.ajaxSetup({
                    headers: {
                        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                    },
                });
                $.ajax({
                    type: "POST",
                    url: baseBackend + "uploader/deluploader",
                    data: "attachement_id=" + currentAttachementId,
                    success: function(msg) {
                       
                    }
                });*/
                inputField.val(JSON.stringify(gObjectAttachements));
            })
        } else {
            el.on('click', '.delete-image', function() {
                // 显示值为空
                el.find('.media-list ul').html('');
                inputField.val('');
 
                // oss删除
                if (gObjectName != '') {
                    fileAttachement = gObjectName;
                }
                 // 后端不做删除
                /*$.ajaxSetup({
                    headers: {
                        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                    },
                });
                $.ajax({
                    type: "POST",
                    url: baseBackend + "uploader/deluploader",
                    data: "attachement_id=" + fileAttachement,
                    success: function(msg) {
                       
                    }
                });*/
            })
        }
 
    })
})

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值