ExtJS-文件上传组件-FileUpload

发布时间 2023-08-24 10:21:18作者: 重庆熊猫

ExtJS教程汇总:https://www.cnblogs.com/cqpanda/p/16328016.html
转载请注明出处:https://www.cnblogs.com/cqpanda/p/17030699.html

更新记录
2023年8月24日 从代码迁移到博客。

完整源代码:
https://gitee.com/panda666plus/ext-js-file-upload-component

FileUpload.js

/**
 * 文件上传管理View
 */
Ext.define('Panda.view.core.fileUpload.FileUpload',{
    extend: 'Ext.window.Window',
    xtype: 'fileupload',
    alias: 'widget.fileupload',
    requires: [
        'Panda.view.core.fileUpload.FileUploadController',
        'Panda.view.core.fileUpload.FileUploadModel'
    ],

    controller: 'core-fileUpload-FileUploadController',
    viewModel: {
        type: 'core-fileUpload-FileUploadModel'
    },

    //region 自定义参数
    /**
     * 上传组件的调用者
     */
    caller: null,

    /**
     * 上传完成后,需要关联数据的容器、变量
     */
    needFillElement: null,

    /**
     * 允许上传的文件类型
     * 格式参考:'.xlsx||.xls||.pdf'
     */
    allowUploadFileType: '',

    /**
     * 上传框顶部的文本
     */
    customPromptText:'请选择上传文件',

    /**
     * 是否允许自定义文件名称
     */
    allowCustomFileName: false,

    /**
     * 是否允许取消文件上传
     */
    allowCancelFileUpload: true,

    /**
     * 上传成功后的回调函数
     */
    uploadSuccessCallback: null,

    /**
     * 上传出现错误回调函数
     */
    uploadErrorCallback: null,

    /**
     * 上传完成回调函数(不论是否成功)
     */
    uploadFinishCallback: null,
    //endregion

    /**
     * 构造函数
     * @param configs 参数
     */
    constructor:function (configs) {
        //初始化调用者参数
        Ext.apply(this, configs);

        //调用父类构造函数
        this.callParent(configs);

        //初始化上传组件
        this.initUploadPanel();
    },

    /***
     * 初始化上传组件
     */
    initUploadPanel:function () {
        //设置窗口的标题
        this.setTitle(this.customPromptText);
    },

    closable: true,
    listeners: {
        beforeclose: 'onCloseButtonClickEventHandler',
    },
    scrollable: true,
    minHeight: 150,
    maxHeight: 300,
    minWidth: 200,
    maxWidth: 500,
    layout: 'fit',
    items: [
        {
            xtype: 'form',
            reference: 'uploadForm',
            padding: '20px',
            items: [
                {
                    xtype: 'container',
                    width: '100%',
                },
                {
                    xtype: 'filefield',
                    reference: 'uploadFile',
                    width: '100%',
                },
                {
                    xtype: 'textfield',
                    fieldLabel: '自定义文件名(选填)',
                    labelWidth: 175,
                    reference: 'userDefineFileName',
                    name: 'userDefineFileName',
                    width: '100%',
                },
            ]
        }
    ],
    buttons: [
        {
            text: '开始上传',
            handler: 'onSubmitUploadButtonClickEventHandler',
        },
        {
            text: '取消上传',
            handler: 'onCancelSubmitButtonClickEventHandler',
        },
    ],
});

FileUploadController.js

/**
 * 文件上传管理Controller
 */
Ext.define('Panda.view.core.fileUpload.FileUploadController', {
    extend: 'Ext.app.ViewController',
    alias: 'controller.core-fileUpload-FileUploadController',

    //文件上传使用的Ajax请求引用
    //用于取消请求
    fileUploadAjaxRequest: null,

    /**
     * 提交上传按钮事件处理函数
     */
    onSubmitUploadButtonClickEventHandler: function () {

        //先让调用上传组件的View进行mask
        this.callerViewMasked();
        //让Window进行遮罩
        this.getView().mask("文件上传中...");

        //控制器作用域
        let controllerScope = this;
        //获得应用引用
        let app = Ext.getApplication();
        //上传路径URL
        let uploadUrl = app.coreApi.getApiUrl('fileUploadPath');
        //获得文件名(用户设置的)(值)
        let userDefineFileName = this.lookupReference('userDefineFileName').getValue();
        //文件上传组件
        let uploadFileComponent = this.lookupReference('uploadFile');
        //文件上传表单DOM组件
        let fileUploadDomElement = uploadFileComponent.fileInputEl.dom;

        //region 验证是否表单是否为空
        //验证文件表单是否有值
        if(uploadFileComponent.getValue() === "")
        {
            //提示用户
            Ext.Msg.alert("温馨提示", "您未选择任何文件,请选择文件后再上传。");
            //取消遮罩(父元素)
            this.callerViewUnmasked();
            //取消遮罩
            this.getView().unmask();
            return;
        }
        //endregion

        //region 验证是否允许的文件类型
        //获得用户选择的文件的后缀
        let filePath = uploadFileComponent.getValue();
        let userSelectFileType = filePath.substring(filePath.lastIndexOf('.'));
        //允许的文件类型
        let allowFileTypes = this.getView().allowUploadFileType.split("||");
        //遍历是否有文件服务,有任何一个符合就返回
        let isAllowFileType = Ext.Array.some(allowFileTypes, function (item) {
            return item.trim() == userSelectFileType.toLowerCase();
        });

        //不符合就进行返回
        if(!isAllowFileType)
        {
            Ext.Msg.alert("温馨提示", "目前暂不支持您选择的文件类型或您选择的文件类型有误,请选择以下类型的文件:" + allowFileTypes.join('、') + '。');
            //取消遮罩(父元素)
            this.callerViewUnmasked();
            //取消遮罩
            this.getView().unmask();
            return;
        }

        //endregion

        //region 发送数据到后端
        //创建表单数据
        let formData =new FormData();
        //表单数据加入上传的文件
        formData.append('uploadFile',fileUploadDomElement.files[0]);
        //表单数据加入上传的自定义文件名称
        formData.append('fileSaveName',userDefineFileName);

        //发起Ajax请求
        this.fileUploadAjaxRequest = Ext.Ajax.request({
            url: uploadUrl,
            cors: true,
            useDefaultXhrHeader: false,
            method: 'post',
            rawData: formData,    //原始数据
            headers: {
                /*
                    最重要的部分,将Content-Type设置成null,
                    ExtJs则会由内部的XMLHTTPRequest自动生成包含boundary的Content-Type,
                    否则在使用rawData的情况下,
                    ExtJs会将Content-Type设置成text/plain
                */
                "Content-Type":null
            },
            success:function (response,options) {
                //取消调用程序的遮罩
                controllerScope.callerViewUnmasked();
                //取消Window遮罩
                controllerScope.getView().unmask();

                //获得后端的数据
                let responseData = Ext.decode(response.responseText);

                //如果上传成功
                if(responseData.success)
                {
                    //消息提示
                    Ext.Msg.alert('温馨提示', responseData.message,function () {
                        //需要填充数据的容器
                        let needFillElement = controllerScope.getView().needFillElement;
                        //为需要上传完成后,返回数据的容器填充数据
                        //如果是图片组件
                        if(needFillElement.setSrc)
                        {
                            needFillElement.setSrc(app.coreApi.filePathInServer);
                        }
                        else if(needFillElement.setValue) //如果是普通表单组件
                        {
                            needFillElement.setValue(responseData.data.filePathInServer);
                        }
                        else if(Ext.typeOf(needFillElement) == 'string') //如果是字符串
                        {
                            needFillElement = responseData.data.filePathInServer;
                        }
                        //关闭window
                        controllerScope.getView().close();
                    });
                }
                else //上传不成功
                {
                    Ext.Msg.alert('温馨提示', responseData.message,function () {
                        //关闭window
                        controllerScope.getView().close();
                    });
                }
            },
            failure:function (response,options) {
                //取消调用程序的遮罩
                controllerScope.callerViewUnmasked();
                //取消Window遮罩
                controllerScope.getView().unmask();

                //获得后端的数据
                let responseData = Ext.decode(response.responseText);

                //上传不成功
                if(!responseData.success)
                {
                    Ext.Msg.alert('温馨提示', '文件上传错误。错误信息:' + responseData.message);
                    return;
                }

                //消息提示
                Ext.Msg.alert('温馨提示', '文件上传错误。');
            }
        });

        //endregion
    },

    /**
     * 取消上传按钮事件处理函数
     */
    onCancelSubmitButtonClickEventHandler: function () {
        //取消mask
        this.callerViewUnmasked();
        //取消Window遮罩
        this.getView().unmask();

        //取消Ajax请求
        Ext.Ajax.abort(this.fileUploadAjaxRequest);

        //关闭Window
        this.getView().close();
    },

    /**
     * 用户点击关闭按钮事件处理函数
     */
    onCloseButtonClickEventHandler: function( panel, eOpts ) {
        //取消mask
        this.callerViewUnmasked();

        //取消Ajax请求
        Ext.Ajax.abort(this.fileUploadAjaxRequest);
    },

    /**
     * 对调用者的视图进行mask
     */
    callerViewMasked: function (){
        //调用者的View进行mask
        //注意caller定义在View中
        //注意caller传入的是Controller类型
        this.getView().caller.getView().mask();
    },

    /**
     * 对调用者的视图进行取消mask
     */
    callerViewUnmasked: function (){
        //注意caller定义在View中
        //注意caller传入的是Controller类型
        this.getView().caller.getView().unmask();
    },
});

FileUploadModel.js

/**
 * 文件上传管理ViewModel
 */
Ext.define('Panda.view.core.fileUpload.FileUploadModel', {
    extend: 'Ext.app.ViewModel',
    alias: 'viewmodel.core-fileUpload-FileUploadModel',
});