Results 1 to 4 of 4

Thread: CRUD with file upload

  1. #1
    Sencha User
    Join Date
    Dec 2008
    Location
    France
    Posts
    321
    Answers
    5

    Default Answered: CRUD with file upload

    Hello,

    I'm performing CRUD operations, fully inspired from the restful / writer examples of Extjs.
    In my form, i've also a file upload field.
    But it is not posted.

    The store is :

    Code:
                remoteFilter: true,
                remoteSort: true,
                storeId: 'CategorieStore',
                autoLoad: false,
                autoSync: true,
                model: 'MyModel.model.CategorieModel',
                proxy: {
                    type: 'rest',
                    api: {
                        read: 'php/admin/app.php/categories/view',
                        create: 'php/admin/app.php/categories/create',
                        update: 'php/admin/app.php/categories/update',
                        destroy: 'php/admin/app.php/categories/destroy'
                    },
                    reader: {
                        type: 'json',
                        messageProperty: 'msgerror',
                        rootProperty: 'data'
                    },
                    writer: {
                        type: 'json',
                        clientIdProperty: 'clientId',
                        rootProperty: 'data'
                    },
                    listeners: {
                        exception: {
                            fn: me.onAjaxException,
                            scope: me
                        }
                    }
                }
    When i perform a Create operation, the POST datas are :

    Code:
    JSON
        data    Object
            libelle_categorie    FHFHFGH
            image_categorie                    <-- Nothing here
            .....

    My question : how to perform a CRUD operation when there's a file upolad field ?

  2. Come back to this after some monthes, with new needs.

    I use an other way to load file via CRUD operations : the Javascript' API "File", and store the file (image) in PgSQL database.

    Here's the complete code for help to some of you if needed.

    The model
    Code:
    Ext.define('MY_APP.model.annuaire.AnnuaireCadreModel', {
        extend: 'Ext.data.Model',
        alias: 'model.annuaire_cadre',
    
        requires: [
            'Ext.data.field.Integer',
            'Ext.data.field.Boolean',
            'Ext.data.field.String'
        ],
    
        fields: [
            {
                type: 'int',
                name: 'id_cadre'
            },
            {
                type: 'boolean',
                defaultValue: 0,
                name: 'modification'
            },
            {
                type: 'boolean',
                defaultValue: 0,
                name: 'suppression'
            },
            {
                type: 'string',
                name: 'patronyme'
            },
            {
                type: 'string',
                name: 'date_de_naissance'
            },
            {
                type: 'string',
                name: 'photo'
            }
        ]
    });
    The store
    Code:
    Ext.define('MY_APP.store.annuaire.AnnuaireCadre', {
        extend: 'Ext.data.Store',
    
        requires: [
            'MY_APP.model.annuaire.AnnuaireCadreModel',
            'Ext.data.proxy.Rest',
            'Ext.data.reader.Json',
            'Ext.data.writer.Json'
        ],
    
        constructor: function(cfg) {
            var me = this;
            cfg = cfg || {};
            me.callParent([Ext.apply({
                remoteFilter: true,
                remoteSort: true,
                storeId: 'annuaire.AnnuaireCadre',
                model: 'MY_APP.model.annuaire.AnnuaireCadreModel',
                proxy: {
                    type: 'rest',
                    url: 'php/application/app.php/annuaire_cadre',
                    reader: {
                        type: 'json',
                        rootProperty: 'data'
                    },
                    listeners: {
                        exception: {
                            fn: me.onRestException,
                            scope: me
                        }
                    },
                    writer: {
                        type: 'json',
                        allDataOptions: {
                            associated: true,
                            persist: true
                        }
                    }
                }
            }, cfg)]);
        },
    
        onRestException: function(proxy, response, operation, eOpts) {
            var reponse = Ext.JSON.decode(response.responseText);
            Ext.MessageBox.show({
                title: reponse.title,
                msg: reponse.message,
                icon: Ext.MessageBox.ERROR,
                buttons: Ext.Msg.OK
            }).center();
        }
    
    });
    The grid to list the datas
    Code:
    Ext.define('MY_APP.view.annuaire.listeAnnuCadre', {
        extend: 'Ext.grid.Panel',
        alias: 'widget.annuaire.listeannucadre',
    
        requires: [
            'MY_APP.view.annuaire.listeAnnuCadreViewModel',
            'MY_APP.view.annuaire.listeAnnuCadreViewController',
            'Ext.grid.column.Action',
            'Ext.view.Table',
            'Ext.XTemplate'
        ],
    
        controller: 'annuaire.listeannucadre',
        viewModel: {
            type: 'annuaire.listeannucadre'
        },
        cls: 'annuaire_cadre',
        tpl: [   //<== some tpl with css to display datas
            '<div class="cadre-data">',
            '<div class="cadre-line">',
            '<div class="cadre-picture">',
            '<img src="{photo}">',
            '</div>',
            '<div class="cadre-content">',
            '<div class="cadre-patronyme">',
            '{patronyme}',
            '</div>',
            '<div>',
            '{date_de_naissance}',
            '</div>',
            '</div>',
            '</div>',
            '</div>'
        ],
        hideHeaders: true,
        rowLines: false,
        store: 'annuaire.AnnuaireCadre',
    
        columns: [
            {
                xtype: 'actioncolumn',
                getClass: function(v, metadata, r, rowIndex, colIndex, store) {
                    if (v === false) {
                        return '';
                    } else if (v === true) {
                        return 'modifieGridCls';
                    }
                },
                getTip: function(value, metadata, record, rowIndex, colIndex, store) {
                    if (value === false) {
                        return '';
                    } else if (value === true) {
                        return 'Click to change datas</u></b>';
                    }
                },
                isActionDisabled: function(view, rowIndex, colIndex, item, record) {
                    return !record.data.modification;
                },
                handler: 'listeAnnuCadreModification',
                draggable: false,
                resizable: false,
                width: 35,
                sortable: false,
                align: 'center',
                dataIndex: 'modification',
                menuDisabled: true
            },
            {
                xtype: 'actioncolumn',
                handler: 'listeAnnuCadreSuppression',
                getClass: function(v, metadata, r, rowIndex, colIndex, store) {
                    if (v === false) {
                        return '';
                    } else if (v === true) {
                        return 'supprimeGridCls';
                    }
                },
                getTip: function(value, metadata, record, rowIndex, colIndex, store) {
                    if (value === false) {
                        return '';
                    } else if (value === true) {
                        return 'Clito delete datas</u></b>';
                    }
                },
                isActionDisabled: function(view, rowIndex, colIndex, item, record) {
                    return !record.data.suppression;
                },
                draggable: false,
                resizable: false,
                width: 35,
                sortable: false,
                align: 'center',
                dataIndex: 'suppression',
                menuDisabled: true
            },
            {
                xtype: 'gridcolumn',
                renderer: 'renderNomColumn',
                flex: 1,
                dataIndex: 'patronyme'
            }
        ]
    
    });
    The form to add datas
    Code:
    Ext.define('MY_APP.view.annuaire.FormAnnuCadre', {
        extend: 'Ext.form.Panel',
        alias: 'widget.annuaire.formannucadre',
    
        requires: [
            'MY_APP.view.annuaire.FormAnnuCadreViewModel',
            'MY_APP.view.annuaire.FormAnnuCadreViewController',
            'Ext.form.field.Display',
            'Ext.form.field.ComboBox',
            'Ext.form.field.File',
            'Ext.form.field.Date',
            'Ext.form.field.Hidden',
            'Ext.Img',
            'Ext.grid.Panel',
            'Ext.view.Table',
            'Ext.grid.column.Date',
            'Ext.grid.plugin.RowEditing',
            'Ext.toolbar.Toolbar',
            'Ext.button.Button'
        ],
    
        controller: 'annuaire.formannucadre',
        viewModel: {
            type: 'annuaire.formannucadre'
        },
        id: 'id_FormAnnuCadre',
        scrollable: false,
        bodyPadding: 10,
        defaultListenerScope: true,
    
        initConfig: function(instanceConfig) {
            var me = this,
                config = {
                    items: [
                        {
                            xtype: 'displayfield',
                            anchor: '100%',
                            value: 'Some text or help'
                        },
                        {
                            xtype: 'container',
                            margin: '0 0 10 0',
                            layout: 'column',
                            items: [
                                {
                                    xtype: 'container',
                                    columnWidth: 0.9,
                                    layout: 'anchor',
                                    items: [
                                        {
                                            xtype: 'combobox',
                                            anchor: '80%',
                                            fieldLabel: 'Agent',
                                            labelAlign: 'right',
                                            labelWidth: 150,
                                            name: 'id_cadre',
                                            allowBlank: false,
                                            emptyText: '3 or 4 char of the name...',
                                            displayField: 'libelle_utilisateur',
                                            minChars: 3,
                                            store: 'administration.utilisateur',
                                            typeAhead: true,
                                            valueField: 'id_utilisateur'
                                        },
                                        {
                                            xtype: 'filefield',
                                            anchor: '80%',
                                            id: 'id_photo_path',
                                            fieldLabel: 'Photo',
                                            labelAlign: 'right',
                                            labelWidth: 150,
                                            listeners: {
                                                change: 'onAttachmentChange'  //<== to show the image after choosing it
                                            }
                                        },
                                        me.processDate_de_naissance({
                                            xtype: 'datefield',
                                            anchor: '50%',
                                            fieldLabel: 'Date de naissance',
                                            labelAlign: 'right',
                                            labelWidth: 150,
                                            name: 'date_de_naissance',
                                            showToday: false
                                        }),
                                        {
                                            xtype: 'hiddenfield',
                                            id: 'id_photo',
                                            name: 'photo'
                                        }
                                    ]
                                },
                                {
                                    xtype: 'image',   //<== where the image will be shown
                                    height: 120,
                                    id: 'photo_thumb',
                                    width: 120,
                                    src: '%22%22'
                                }
                            ]
                        },
                        {
                            xtype: 'container',
                            padding: 10,
                            layout: {
                                type: 'hbox',
                                align: 'middle',
                                pack: 'center'
                            },
                            items: [
                                {
                                    xtype: 'button',
                                    margin: '0 10 0 0',
                                    width: 150,
                                    iconCls: 'x-fa fa-remove',
                                    text: 'Annuler',
                                    listeners: {
                                        click: {
                                            fn: 'cancelEdit',
                                            scope: 'controller'
                                        }
                                    }
                                },
                                {
                                    xtype: 'button',
                                    formBind: true,
                                    disabled: true,
                                    margin: '0 0 0 10',
                                    width: 150,
                                    iconCls: 'x-fa fa-check',
                                    text: 'Enregistrer',
                                    listeners: {
                                        click: {
                                            fn: 'save',
                                            scope: 'controller'
                                        }
                                    }
                                }
                            ]
                        }
                    ]
                };
            if (instanceConfig) {
                me.self.getConfigurator().merge(me, config, instanceConfig);
            }
            return me.callParent([config]);
        },
    
        processDate_de_naissance: function(config) {
            config.maxValue = Ext.Date.add(new Date(), Ext.Date.YEAR, -18);
            config.minValue = Ext.Date.add(new Date(), Ext.Date.YEAR, -67);
            config.value = Ext.Date.add(new Date(), Ext.Date.YEAR, -18);
            return config;
        },
    
        onAttachmentChange: function(filefield, value, eOpts) { //<== the function to show the image in the image field, using the Javascript' API "File"
            var file = filefield.fileInputEl.dom.files[0],
                reader;
    
            if (file === undefined || !(file instanceof File)) {
                return;
            }
    
            reader = new FileReader();
            reader.onload = function (event) {
                Ext.getCmp('photo_thumb').setSrc(event.target.result);
    
            };
            reader.readAsDataURL(file);
        }
    
    });
    The ViewController's form
    Code:
    Ext.define('MY_APP.view.annuaire.FormAnnuCadreViewController', {
        extend: 'Ext.app.ViewController',
        alias: 'controller.annuaire.formannucadre',
    
        cancelEdit: function(button, e, eOpts) {
            this.getView().getForm().reset();
        },
    
        save: function(button, e, eOpts) {
            var form = this.getView().getForm(),
                values,
                model,
                store = Ext.getStore('annuaire.AnnuaireCadre');
    
            if (form.isValid()) {
                // Check for the various File API support.
                if (window.File && window.FileReader && window.FileList && window.Blob) {
    
    //*******************************************************************************************************
     // We use the Javascript' API "File" to read the file as dataurl
    // Then put the data url in the field "id_photo"
    // Then add the form's values in the store's model
    // Then sync the store
    //*******************************************************************************************************
                    var file = Ext.getCmp('id_photo_path').fileInputEl.dom.files[0],
                        reader;
    
                    if (file === undefined || !(file instanceof File)) {
                        return;
                    }
    
                    reader = new FileReader();
                    reader.readAsDataURL(file);
                    reader.onload = function (event) {
                        Ext.getCmp('id_photo').setValue(event.target.result);
                        values = form.getValues();
                        model = Ext.create('model.annuaire_cadre', values);
                        store.add(model);
                        store.sync({
                            success: function(batch, options) {
                                response = Ext.decode(batch.operations[0].getResponse().responseText);
                                Ext.Msg.show({
                                    title: response.title,
                                    msg: response.message,
                                    buttons: Ext.Msg.OK,
                                    scope: this,
                                    icon: Ext.Msg.INFO
                                });
                            }
                        });
                    };
                } else {
                    alert('The File APIs are not fully supported in this browser.');
                }
            } else {
                Ext.Msg.show({
                    title: 'Error',
                    msg: 'Some erros, please check !',
                    buttons: Ext.Msg.OK,
                    animateTarget: button,
                    scope: this,
                    icon: Ext.Msg.ERROR
                });
            }
        }
    
    });

    In the PgSQL database, use a BYTEA column to store the data (the name of the column i've choosen : photo)

    In PHP script, think to escape before inserting :
    Code:
    pg_escape_bytea($_POST['photo'])
    When selecting in the SQL :
    Code:
    SELECT ENCODE(photo, 'base64') as photo
    When sending dats from PHP :
    Code:
    base64_decode($my_pg_query_result["photo"])

  3. #2

    Default

    Hmm, just a question. can this work any way when you define Content-Type : application(/json with type json? You need to pass the file(s) with Content-Type multipart/form-data to your server to instruct him to handle the file byte array or not? (Perhaps you have a real clever server...). May be it is suitable for you to upload the file in front and then pass the file reference (in our case a relative path pointing to some AWS endpoint) to your model and save it when the promise/callback is resolved/successfule with the created path. In some rare cases we have orphans in the bucket, but they will be picked up by another process matching valid file references....


    We use this code for posting form-data to our (node.js server):
    Code:
    upload(name, dataBuffer,showProgress){
        let endpoint =  'ENDPOINT/upload',
            url = $App.resolveUrl('assets-app',endpoint),
            data = new FormData()
    
        //TODO: Sanity Checks for data
    data.append('name',name)
        data.append('imgFile', dataBuffer);
    
        return new Promise((resolve, reject) => {
    
            if(!name){
                reject({
                    errorMessage : 'No name for the asset to upload passed'
    })
            }
            if(!data){
                reject({
                    errorMessage : 'No data to upload passed'
    })
            }
    
            if(showProgress){
                console.error('showProgress in console currently not yet imeplemented')
            }
    
            Ext.Ajax.request({
                url,
                rawData: data,
                //waitMsg: 'Uploading asset to Server ...',
    headers: {'Content-Type':null}, //to use content type of FormData
    success(response){
                    resolve(JSON.parse(response.responseText))
                },
                failure(response){
                    if (response.status === 200) {
                        resolve(JSON.parse(response.responseText))
                    } else {
                        reject({
                            message: response.responseText,
                            status: response.status,
                        })
                    }
                }
            });
    
        })
    }
    
    Greetings Olli

  4. #3
    Sencha User
    Join Date
    Dec 2008
    Location
    France
    Posts
    321
    Answers
    5

    Default

    Quote Originally Posted by aicgroup-dev View Post
    You need to pass the file(s) with Content-Type multipart/form-data to your server to instruct him to handle the file byte array
    I've tried to add a header in the proxy :
    Code:
    headers: {
       'Content-Type': 'multipart/form-data; boundary=---------------------------254791272615366'
    },
    But nothing in the server side about all datas coming from the Create operation : $_POST, $_REQUEST, $_FILES are empty.


    Maybe need to process in 2 times as you explain : first for the file, second for the other datas.
    I will try it.

  5. #4
    Sencha User
    Join Date
    Dec 2008
    Location
    France
    Posts
    321
    Answers
    5

    Default

    Come back to this after some monthes, with new needs.

    I use an other way to load file via CRUD operations : the Javascript' API "File", and store the file (image) in PgSQL database.

    Here's the complete code for help to some of you if needed.

    The model
    Code:
    Ext.define('MY_APP.model.annuaire.AnnuaireCadreModel', {
        extend: 'Ext.data.Model',
        alias: 'model.annuaire_cadre',
    
        requires: [
            'Ext.data.field.Integer',
            'Ext.data.field.Boolean',
            'Ext.data.field.String'
        ],
    
        fields: [
            {
                type: 'int',
                name: 'id_cadre'
            },
            {
                type: 'boolean',
                defaultValue: 0,
                name: 'modification'
            },
            {
                type: 'boolean',
                defaultValue: 0,
                name: 'suppression'
            },
            {
                type: 'string',
                name: 'patronyme'
            },
            {
                type: 'string',
                name: 'date_de_naissance'
            },
            {
                type: 'string',
                name: 'photo'
            }
        ]
    });
    The store
    Code:
    Ext.define('MY_APP.store.annuaire.AnnuaireCadre', {
        extend: 'Ext.data.Store',
    
        requires: [
            'MY_APP.model.annuaire.AnnuaireCadreModel',
            'Ext.data.proxy.Rest',
            'Ext.data.reader.Json',
            'Ext.data.writer.Json'
        ],
    
        constructor: function(cfg) {
            var me = this;
            cfg = cfg || {};
            me.callParent([Ext.apply({
                remoteFilter: true,
                remoteSort: true,
                storeId: 'annuaire.AnnuaireCadre',
                model: 'MY_APP.model.annuaire.AnnuaireCadreModel',
                proxy: {
                    type: 'rest',
                    url: 'php/application/app.php/annuaire_cadre',
                    reader: {
                        type: 'json',
                        rootProperty: 'data'
                    },
                    listeners: {
                        exception: {
                            fn: me.onRestException,
                            scope: me
                        }
                    },
                    writer: {
                        type: 'json',
                        allDataOptions: {
                            associated: true,
                            persist: true
                        }
                    }
                }
            }, cfg)]);
        },
    
        onRestException: function(proxy, response, operation, eOpts) {
            var reponse = Ext.JSON.decode(response.responseText);
            Ext.MessageBox.show({
                title: reponse.title,
                msg: reponse.message,
                icon: Ext.MessageBox.ERROR,
                buttons: Ext.Msg.OK
            }).center();
        }
    
    });
    The grid to list the datas
    Code:
    Ext.define('MY_APP.view.annuaire.listeAnnuCadre', {
        extend: 'Ext.grid.Panel',
        alias: 'widget.annuaire.listeannucadre',
    
        requires: [
            'MY_APP.view.annuaire.listeAnnuCadreViewModel',
            'MY_APP.view.annuaire.listeAnnuCadreViewController',
            'Ext.grid.column.Action',
            'Ext.view.Table',
            'Ext.XTemplate'
        ],
    
        controller: 'annuaire.listeannucadre',
        viewModel: {
            type: 'annuaire.listeannucadre'
        },
        cls: 'annuaire_cadre',
        tpl: [   //<== some tpl with css to display datas
            '<div class="cadre-data">',
            '<div class="cadre-line">',
            '<div class="cadre-picture">',
            '<img src="{photo}">',
            '</div>',
            '<div class="cadre-content">',
            '<div class="cadre-patronyme">',
            '{patronyme}',
            '</div>',
            '<div>',
            '{date_de_naissance}',
            '</div>',
            '</div>',
            '</div>',
            '</div>'
        ],
        hideHeaders: true,
        rowLines: false,
        store: 'annuaire.AnnuaireCadre',
    
        columns: [
            {
                xtype: 'actioncolumn',
                getClass: function(v, metadata, r, rowIndex, colIndex, store) {
                    if (v === false) {
                        return '';
                    } else if (v === true) {
                        return 'modifieGridCls';
                    }
                },
                getTip: function(value, metadata, record, rowIndex, colIndex, store) {
                    if (value === false) {
                        return '';
                    } else if (value === true) {
                        return 'Click to change datas</u></b>';
                    }
                },
                isActionDisabled: function(view, rowIndex, colIndex, item, record) {
                    return !record.data.modification;
                },
                handler: 'listeAnnuCadreModification',
                draggable: false,
                resizable: false,
                width: 35,
                sortable: false,
                align: 'center',
                dataIndex: 'modification',
                menuDisabled: true
            },
            {
                xtype: 'actioncolumn',
                handler: 'listeAnnuCadreSuppression',
                getClass: function(v, metadata, r, rowIndex, colIndex, store) {
                    if (v === false) {
                        return '';
                    } else if (v === true) {
                        return 'supprimeGridCls';
                    }
                },
                getTip: function(value, metadata, record, rowIndex, colIndex, store) {
                    if (value === false) {
                        return '';
                    } else if (value === true) {
                        return 'Clito delete datas</u></b>';
                    }
                },
                isActionDisabled: function(view, rowIndex, colIndex, item, record) {
                    return !record.data.suppression;
                },
                draggable: false,
                resizable: false,
                width: 35,
                sortable: false,
                align: 'center',
                dataIndex: 'suppression',
                menuDisabled: true
            },
            {
                xtype: 'gridcolumn',
                renderer: 'renderNomColumn',
                flex: 1,
                dataIndex: 'patronyme'
            }
        ]
    
    });
    The form to add datas
    Code:
    Ext.define('MY_APP.view.annuaire.FormAnnuCadre', {
        extend: 'Ext.form.Panel',
        alias: 'widget.annuaire.formannucadre',
    
        requires: [
            'MY_APP.view.annuaire.FormAnnuCadreViewModel',
            'MY_APP.view.annuaire.FormAnnuCadreViewController',
            'Ext.form.field.Display',
            'Ext.form.field.ComboBox',
            'Ext.form.field.File',
            'Ext.form.field.Date',
            'Ext.form.field.Hidden',
            'Ext.Img',
            'Ext.grid.Panel',
            'Ext.view.Table',
            'Ext.grid.column.Date',
            'Ext.grid.plugin.RowEditing',
            'Ext.toolbar.Toolbar',
            'Ext.button.Button'
        ],
    
        controller: 'annuaire.formannucadre',
        viewModel: {
            type: 'annuaire.formannucadre'
        },
        id: 'id_FormAnnuCadre',
        scrollable: false,
        bodyPadding: 10,
        defaultListenerScope: true,
    
        initConfig: function(instanceConfig) {
            var me = this,
                config = {
                    items: [
                        {
                            xtype: 'displayfield',
                            anchor: '100%',
                            value: 'Some text or help'
                        },
                        {
                            xtype: 'container',
                            margin: '0 0 10 0',
                            layout: 'column',
                            items: [
                                {
                                    xtype: 'container',
                                    columnWidth: 0.9,
                                    layout: 'anchor',
                                    items: [
                                        {
                                            xtype: 'combobox',
                                            anchor: '80%',
                                            fieldLabel: 'Agent',
                                            labelAlign: 'right',
                                            labelWidth: 150,
                                            name: 'id_cadre',
                                            allowBlank: false,
                                            emptyText: '3 or 4 char of the name...',
                                            displayField: 'libelle_utilisateur',
                                            minChars: 3,
                                            store: 'administration.utilisateur',
                                            typeAhead: true,
                                            valueField: 'id_utilisateur'
                                        },
                                        {
                                            xtype: 'filefield',
                                            anchor: '80%',
                                            id: 'id_photo_path',
                                            fieldLabel: 'Photo',
                                            labelAlign: 'right',
                                            labelWidth: 150,
                                            listeners: {
                                                change: 'onAttachmentChange'  //<== to show the image after choosing it
                                            }
                                        },
                                        me.processDate_de_naissance({
                                            xtype: 'datefield',
                                            anchor: '50%',
                                            fieldLabel: 'Date de naissance',
                                            labelAlign: 'right',
                                            labelWidth: 150,
                                            name: 'date_de_naissance',
                                            showToday: false
                                        }),
                                        {
                                            xtype: 'hiddenfield',
                                            id: 'id_photo',
                                            name: 'photo'
                                        }
                                    ]
                                },
                                {
                                    xtype: 'image',   //<== where the image will be shown
                                    height: 120,
                                    id: 'photo_thumb',
                                    width: 120,
                                    src: '%22%22'
                                }
                            ]
                        },
                        {
                            xtype: 'container',
                            padding: 10,
                            layout: {
                                type: 'hbox',
                                align: 'middle',
                                pack: 'center'
                            },
                            items: [
                                {
                                    xtype: 'button',
                                    margin: '0 10 0 0',
                                    width: 150,
                                    iconCls: 'x-fa fa-remove',
                                    text: 'Annuler',
                                    listeners: {
                                        click: {
                                            fn: 'cancelEdit',
                                            scope: 'controller'
                                        }
                                    }
                                },
                                {
                                    xtype: 'button',
                                    formBind: true,
                                    disabled: true,
                                    margin: '0 0 0 10',
                                    width: 150,
                                    iconCls: 'x-fa fa-check',
                                    text: 'Enregistrer',
                                    listeners: {
                                        click: {
                                            fn: 'save',
                                            scope: 'controller'
                                        }
                                    }
                                }
                            ]
                        }
                    ]
                };
            if (instanceConfig) {
                me.self.getConfigurator().merge(me, config, instanceConfig);
            }
            return me.callParent([config]);
        },
    
        processDate_de_naissance: function(config) {
            config.maxValue = Ext.Date.add(new Date(), Ext.Date.YEAR, -18);
            config.minValue = Ext.Date.add(new Date(), Ext.Date.YEAR, -67);
            config.value = Ext.Date.add(new Date(), Ext.Date.YEAR, -18);
            return config;
        },
    
        onAttachmentChange: function(filefield, value, eOpts) { //<== the function to show the image in the image field, using the Javascript' API "File"
            var file = filefield.fileInputEl.dom.files[0],
                reader;
    
            if (file === undefined || !(file instanceof File)) {
                return;
            }
    
            reader = new FileReader();
            reader.onload = function (event) {
                Ext.getCmp('photo_thumb').setSrc(event.target.result);
    
            };
            reader.readAsDataURL(file);
        }
    
    });
    The ViewController's form
    Code:
    Ext.define('MY_APP.view.annuaire.FormAnnuCadreViewController', {
        extend: 'Ext.app.ViewController',
        alias: 'controller.annuaire.formannucadre',
    
        cancelEdit: function(button, e, eOpts) {
            this.getView().getForm().reset();
        },
    
        save: function(button, e, eOpts) {
            var form = this.getView().getForm(),
                values,
                model,
                store = Ext.getStore('annuaire.AnnuaireCadre');
    
            if (form.isValid()) {
                // Check for the various File API support.
                if (window.File && window.FileReader && window.FileList && window.Blob) {
    
    //*******************************************************************************************************
     // We use the Javascript' API "File" to read the file as dataurl
    // Then put the data url in the field "id_photo"
    // Then add the form's values in the store's model
    // Then sync the store
    //*******************************************************************************************************
                    var file = Ext.getCmp('id_photo_path').fileInputEl.dom.files[0],
                        reader;
    
                    if (file === undefined || !(file instanceof File)) {
                        return;
                    }
    
                    reader = new FileReader();
                    reader.readAsDataURL(file);
                    reader.onload = function (event) {
                        Ext.getCmp('id_photo').setValue(event.target.result);
                        values = form.getValues();
                        model = Ext.create('model.annuaire_cadre', values);
                        store.add(model);
                        store.sync({
                            success: function(batch, options) {
                                response = Ext.decode(batch.operations[0].getResponse().responseText);
                                Ext.Msg.show({
                                    title: response.title,
                                    msg: response.message,
                                    buttons: Ext.Msg.OK,
                                    scope: this,
                                    icon: Ext.Msg.INFO
                                });
                            }
                        });
                    };
                } else {
                    alert('The File APIs are not fully supported in this browser.');
                }
            } else {
                Ext.Msg.show({
                    title: 'Error',
                    msg: 'Some erros, please check !',
                    buttons: Ext.Msg.OK,
                    animateTarget: button,
                    scope: this,
                    icon: Ext.Msg.ERROR
                });
            }
        }
    
    });

    In the PgSQL database, use a BYTEA column to store the data (the name of the column i've choosen : photo)

    In PHP script, think to escape before inserting :
    Code:
    pg_escape_bytea($_POST['photo'])
    When selecting in the SQL :
    Code:
    SELECT ENCODE(photo, 'base64') as photo
    When sending dats from PHP :
    Code:
    base64_decode($my_pg_query_result["photo"])

Similar Threads

  1. Replies: 4
    Last Post: 18 Dec 2014, 10:12 PM
  2. Replies: 1
    Last Post: 2 Oct 2012, 8:02 AM
  3. How to disable file upload field and file upload icon
    By mypen in forum Ext 3.x: Help & Discussion
    Replies: 11
    Last Post: 18 Feb 2011, 7:45 AM
  4. How to disable file upload field and file upload icon
    By mypen in forum Ext 3.x: Help & Discussion
    Replies: 1
    Last Post: 31 Jan 2011, 2:16 AM
  5. How to disable file upload field and file upload icon
    By mypen in forum Sencha Touch 1.x: Discussion
    Replies: 3
    Last Post: 26 Jan 2011, 1:04 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •