Javascript upload files with AJAX

Categorías: 

Etiquetas: 

  • The objective is to save form data with file inputs and AJAX.
  • Step 1: process files before the rest of data, save them to disk and database.
  • Step 2: process the rest of field inputs, validate and the save them all.

HTML

<div id="wrapper">
    <form id="example-form" method="post" action="">
        <div class="form-group">
            <label for="Model[name]">Text input</label>
            <input type="text" class="form-control" name="Model[name]">
        </div>
 
        <div class="form-group">
            <label for="Model[file]">File input</label>
            <input type="file" class="form-control" name="Model[file]">
        </div>
 
        <div class="form-group">
            <label for="Model[file2]">File input 2</label>
            <input type="file" class="form-control" name="Model[file2]">
        </div>
 
        <input type="submit" class="btn btn-primary" value="Send">
 
        <div id="ajax-form-results"></div>
    </form>
</div>

Javascript

// Variable to store your files
var files;
 
// on submit, preprocess files
$('#wrapper').on('submit', 'form', uploadFiles);
 
/**
 * Catch the form submit and upload the files
 * @param {object} event
 * @returns {Boolean}
 */
function uploadFiles(event) {
 
    // create a formdata object and add the files #}
    var filesData = new FormData();
 
    // find files
    var files = [];
    $(this).find('input[type="file"]').each(function() {
        if ($(this).val() !== "") {
            files.push($(this)[0].files[0]);
        }
    });
 
    // if form has files...
    if (files.length > 0) {
        $.each(files, function (key, value) {
            filesData.append(key, value);
        });
        $.ajax({
            url: 'ajaxFileUpload.php',
            type: 'POST',
            data: filesData,
            cache: false,
            dataType: 'json',
            processData: false, // Don't process the files
            contentType: false, // Set content type to false as jQuery will tell the server its a query string request
            success: function (filesData) {
                if (data.success === true) {
                    // success so call function to process the form
                    submitForm(event, filesData);
                } else {
                    // handle errors here
                    $('#ajax-form-results').html(filesData.error);
                }
            },
            error: function (filesData) {
                // handle errors here
                console.log('Errors ajaxFileUpload: ' + filesData.error);
            }
        });
    } else {
        // process the form without files
        submitForm(event, filesData);
    }
    return false;
} // end uploadFiles()
 
 
/**
 * Proccess the form submit
 * @param {object} event
 * @param {object} filesData
 * @returns {void}
 */
function submitForm(event, filesData {
    // create a jQuery object from the form
    var form = $(event.target);
 
    // serialize the form data
    var formData = form.serialize();
 
    // if the form has files, add to formData
    if (filesData.length > 0) {
        $.each(filesData.files, function (key, value) {
            formData = formData + '&filenames[]=' + value;
        });
    }
 
    $.ajax({
        url: 'ajaxSubmitForm.php',
        type: 'POST',
        data: formData,
        cache: false,
        dataType: 'json',
        success: function (data) {
            if (data.success === true) {
                // do whatever, send a OK message for example
                $('#ajax-form-results').html(data.message);
 
                // we can refresh some page content here...
 
            } else {
                // Handle errors here
                $('#ajax-form-results').html(data.error);
            }
 
            // in case we made a submit form by Bootstrap modal, hide it by force
            $('body').removeClass('modal-open');
            $('.modal').modal('hide');
            $('.modal-backdrop').remove();
        },
        error: function (data) {
            // Handle errors here
            console.log('Errors ajaxSubmitForm: ' + data.error);
        }
    });
 
} // end submitForm

ajaxFileUpload.php

<?php
$data = [];
 
// if any files, start...
if (isset($_FILES[0])) {
    $success = true;
    $files = [];
 
    // upload dir example
    $uploadDir = 'uploads/files/';
    if (!is_dir($uploadDir)) {
        mkdir($uploadDir);
    }
 
    foreach ($_FILES as $file) {
        $fileName = time() . '_' . $file['name'];
        if (move_uploaded_file($file['tmp_name'], $uploadDir . basename($fileName))) {
 
            $fileModel = new FileExampleModel();
            $fileModel->filename = $fileName;
            $fileModel->filepath = $uploadDir . $fileName;
            $fileModel->filemime = $file['type'];
            $fileModel->filesize = $file['size'];
            $fileModel->origname = $file['name'];
            $fileModel->status = true;
            if (!$fileModel->save()) {
                $success = false;
                break;
            }
 
            // return id from database to link later in the last step
            $files[] = $fileModel->id;
        } else {
            $success = false;
        }
    }
 
    if ($success === true) {
        $data = ['success' => $success, 'files' => $files];
    } else {
        $data = ['error' => 'There was an error uploading your files'];
    }
} else {
    $data = ['success' => $success];
}
 
echo json_encode($data);

ajaxSubmitForm.php

<?php
$success = false;
$message = null;
 
if (isset($_POST['Model'])) {
 
    // example save Model data
    $model = new ModelExample();
    $model->setAttributes($_POST['Model']);
    $model->validate();
 
    if ($model->save()) {
        // assign files if we send them by 'filenames' value in the javascript function submitForm
        if (isset($_POST['filenames'])) {
            foreach ($_POST['filenames'] as $fileId) {
                $modelFileRelation = new FileExampleRelationModel();
                $modelFileRelation->model_id = $model->id;
                $modelFileRelation->file_id = $fileId;
                $modelFileRelation->save();
            }
        }
        $success = true;
        $message = 'Form submitted correctly';
    } else {
        // if something go wrong, we should control what to do with the uploaded files
        $success = false;
        $message = $model->getErrorMessage();
    }
}
 
echo json_encode(['success' => $success, 'message' => $message]);