Bonjour;

Voilà j'ai réalisé un système d'upload pour l'avatar de l'utilisateur, j'aimerais donc savoir si mon code ci-dessous et assez bon et sécurisé, j'aimerais avoir vos critiques constructives pour m'améliorer, merci.

Mon code HTML :

Dans ce code ci-dessous j'affiche simplement l'avatar actuel de l'utilisateur et j'ai masqué un formulaire avec un input "file".

<div class="card-body">
                        <div class="text-center row clearfix mb-2">
                            <div class="col-12">
                                <div class="user-account-edit-overlay-img width-150 height-150" id="mbt-user-edit-profile-picture">
                                    <div class="user-account-edit-overlay">
                                        <i class="la la-camera"></i>
                                        <span>{{ __('utils/button.update') }}</span>
                                    </div>
                                    <img src="http://www.hotavatars.com/wp-content/uploads/2019/01/I80W1Q0.png" class="profile-image rounded-circle width-150 height-150" alt="Card image">
                                </div>
                            </div>
                        </div>
                        <form method="post" action="{{ route('users.edit.picture') }}" style="display: none;" enctype="multipart/form-data">
                            @csrf
                            <input type="file" name="picture" id="picture" hidden>
                            <input type="text" name="picture_data" id="picture_data" hidden>
                        </form>
                        <a href="" class="d-block text-center font-medium-1 d-none">
                            {{ __('users/edit.delete_the_photo') }}
                        </a>
                    </div>

Image = > https://i.ibb.co/qmp8yXV/Screenshot-6.png

Mon code JS :

Cela permet d'ouvrir l'uploader de fichier et cropper mon image, ensuite une fois l'image sélectionner et cropper par l'utilisateur je renvoie la valeur dans un input (hidden) cette valeur, c'est l'image en base64 et je submit le formulaire pour faire le traitement de l'image.

let user_edit = {

    elementClick: '#mbt-user-edit-profile-picture',
    elementInput: '#picture',
    elementModal: '#mbt-user-edit-profile-picture-modal',
    elementModalImage: '#mbt-user-edit-profile-picture-modal .modal-body > img',
    elementModalSubmit: '#mbt-user-edit-profile-picture-modal .modal-footer button[data-type="submit"]',
    cropper: null,

    init: () => {

        if (user_edit.elementClick.length) {
            $(user_edit.elementClick).click((e) => {
                e.preventDefault();
                user_edit.openFile();
            });
        }

    },

    /**
     * Ici quand je clique sur la photo cela ouvrir l'uploader de fichier.
     */
    openFile: () => {
        $(user_edit.elementInput).trigger('click');

        $(user_edit.elementInput).on('change', (e) => {
            user_edit.onChangeFile(e);
        });

    },

    /**
     * Ici un modal s'ouvre pour cropper mon image et ensuite j'envoie la valeur de l'image dans l'input (picture_data) en base64
     * @param e
     */
    onChangeFile: (e) => {
        let input = $(user_edit.elementInput);
        let modal = $(user_edit.elementModal);
        let image = $(user_edit.elementModalImage)[0];
        let button = $(user_edit.elementModalSubmit);
        let cropper;

        let files = e.target.files;

        let done = (url) => {
            input.value = '';
            image.src = url;
            modal.modal('toggle');
        };

        let reader,
            file,
            url;

        if (files && files.length > 0) {
            file = files[0];

            if (URL) {
                done(URL.createObjectURL(file));
            } else if (FileReader) {
                reader = new FileReader();
                reader.onload = (e) => {
                    done(reader.result);
                };
                reader.readAsDataURL(file);
            }
        }

        modal.on('shown.bs.modal', () => {
            cropper = new Cropper(image, {
                aspectRatio: 1,
                viewMode: 3,
            });
        }).on('hidden.bs.modal', () => {
            cropper.destroy();
            cropper = null;
        });

        button.on('click', () => {
            let canvas;

            modal.modal('hide');

            if (cropper) {
                canvas = cropper.getCroppedCanvas({
                    width: 160,
                    height: 160,
                });

                $(user_edit.elementClick + ' > img')[0].src = canvas.toDataURL();
                $("#picture_data").val(canvas.toDataURL());
                input.parent().submit();
            }
        });

    },
};
$(user_edit.init);

Mon code PHP :

Dans ce code PHP, cela permet de récupérer la valeur du base64. Je génère ensuite un nom pour l'image et je l'upload dans mon dossier (Storage) dans le répertoire public.

 private function generateNamePicture($file)
    {

        $filename_original = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);

        if (strlen($filename_original) > 35) {
            $filename_original = substr($file->getClientOriginalName(), 0, 35);
        }

        return $this->authManager->user()->id . $filename_original . time() . $file->getClientOriginalName();

    }

    public function updatePicture(Request $request)
    {
        $picture = $request->file('picture');
        $picture_data = $request->get('picture_data');
        $picture_data = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $picture_data));

        $filename = $this->generateNamePicture($picture);

        Storage::disk('public')->put($filename, $picture_data);

    }

Je vous remercie.

2 réponses


Bonjour,

A quel moment vous vérifier le type de fichier ?

Mariolo
Auteur

Bonjour,

merci de votre remarque, effectivement je fais aucune vérification de type de fichier, je vais rajouter ça.

Merci.