文件上传未通过ajax提交

文件上传未通过ajax提交

问题描述:

I created a form upload which contains some inputs but when I submitted the form to ajax, ajax was unable to grap the file name.

I keep on getting Notice: Undefined index: userImage in C:\wamp\www\osun\i_admin\php_action\uploadImage.php on line 14 . userImage is the name of the file

index.php

<?php include('header.php'); ?>
<?php include('top.php'); ?>
<?php include('links.php'); ?>

    <section class="content">
        <div class="container-fluid">
            <div class="block-header">
                <h2>Worker of the Month</h2>
            </div>

 <!-- Basic -->
 <div class="row clearfix">
                <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
                    <div class="card">

                    <div id="error" class="closeit"></div>

                    <div id="messages"></div>

                         <div class="body">
                         <form  enctype="multipart/form-data" id="uploadImageForm">
                                 <div class="form-group form-float">
                                    <div class="form-line">
                                        <input type="text" class="form-control" name="name" id="name">
                                        <label class="form-label">Worker's Name</label>
                                    </div>
                                </div>

                                 <div class="form-group form-float">
                                    <div class="form-line">
                                        <input type="text" class="form-control" name="dept" id="dept">
                                        <label class="form-label">Department</label>
                                    </div>
                                </div>

                                <div class="form-group form-float">
                                            <div class="input-group">
                                               <div class="form-line">
                                                    <input type="text" data-type="date" id="date" name="date" placeholder="Date" class="form-control datepicker">

                                              </div>

                                             </div>
                                </div>

                                <div class="form-group form-float">
                                    <div class="form-line">
                                        <textarea name="description" id="description"  cols="30" rows="5" class="form-control no-resize"></textarea>
                                        <label class="form-label">Description</label>
                                    </div>
                                </div>


                            <div class="form-group">
                            <label for="exampleInputPassword1">Photo</label>            
                            <div id="kv-avatar-errors-2" class="center-block" style="width:800px;display:none"></div>

                            <div class="kv-avatar center-block" style="width:200px">
                                <input id="avatar-2" name="userImage" type="file" class="file-loading">
                            </div>
                        </div>


                                <div class="form-group" align="center">

                                <button type="input" name="submit"  class="btn btn-success btn-md btn-icon  waves-effect" id="btn-submit" ><i class="fa fa-check-square-o"></i> Save</button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
            <!-- #END# Basic -->
      </div>
    </section>

<?php include('footer.php'); ?>  

uploadimage.php

include('../../includes/functions.php');

if($_POST) {

    $valid = array('success' => false, 'messages' => array());

    $name = $mysqli->real_escape_string($_POST['name']);// user name
    $dept = $mysqli->real_escape_string($_POST['dept']); 
    $desc = $mysqli->real_escape_string($_POST['description']);// user email
    $yr = $mysqli->real_escape_string($_POST['date']); 

    $fileName = $_FILES['userImage']['name'];

    $type = explode('.', $fileName);
    $type = $type[count($type) - 1];

    $url = '../user_images/' . uniqid(rand()) . '.' . $type;

    if(in_array($type, array('gif', 'jpg', 'jpeg', 'png'))) {
        if(is_uploaded_file($_FILES['userImage']['tmp_name'])) {
            if(move_uploaded_file($_FILES['userImage']['tmp_name'], $url)) {

                // insert into database
                $sql = "INSERT INTO worker_of_the_month (name, dept, description, given, img) VALUES ('$name','$dept','$desc','$yr', '$url')";

                if($mysqli->query($sql) === TRUE) {
                    $valid['success'] = true;
                    $valid['messages'] = "Successfully Saved.";
                } 
                else {
                    $valid['success'] = false;
                    $valid['messages'] = "Error while saving. " . $mysqli->error;
                }

                $mysqli->close();

            }
            else {
                $valid['success'] = false;
                $valid['messages'] = "Error while saving. " . $mysqli->error;
            }
        }
    }

    echo json_encode($valid);

    // upload the file 
}

Ajax.js

$('document').ready(function() {
    /* validation */
    $("#uploadImageForm").validate({
        rules:
        {

         name:{
           required: true
         },

         dept:{
           required: true
         },


        description:{
          required: true
        },

        date:{
          required: true
        },

        },
        messages:
        {
          name: "Worker name required",
          dept: "Worker department name required",
          description: "Enter description for this honour.",
          date: "Please select date",
        },
        submitHandler: submitForm
    });
    /* validation */

    /* form submit */
    function submitForm()
    {
        var data = $("#uploadImageForm").serialize();

        $.ajax({

            type : 'POST',
            url  : 'php_action/uploadImage.php',
            data : data,
            beforeSend: function()
            {
                $("#error").fadeOut();
                $("#btn-submit").html('<img src="../img/processing.gif" width="30" /> &nbsp; processing');
            },
            success :  function(data)
            {
               if(data.success == true)
                {
                    $("#btn-submit").html('<img src="../img/processing.gif" width="30" /> &nbsp; Saving ...');
                    $("#messages").html('<div class="alert alert-success alert-dismissible" role="alert">'+
                          '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>'+
                          data.messages + 
                        '</div>');

                          $('#uploadImageForm')[0].reset();
                     /*setTimeout(' window.location.href = "success.php"; ',4000);*/
                }
                else{

                    $("#error").fadeIn(1000, function(){

                        $("#error").html('<div class="alert alert-danger"><span class="glyphicon glyphicon-info-sign"></span> &nbsp; '+data+' !</div>');

                        $("#btn-submit").html('<span class="fa fa-check-square-o"></span> &nbsp; Save');

                    });

                }
            }
        });
        return false;
    }
    /* form submit */

});
    </script>

What am I doing wrong?

You need to use a FormData() to pass files.

Change

var data = $('#uploadImageForm').serialize();

to

var form = $('#uploadImageForm')[0];    
var data = new FormData(form);

As @ThisGuyHasTwoThumbs pointed you should set cache, contentType and processData via your ajax call

$.ajax({
cache: false,
processData: false,
contentType: false,
//other ajax parameters
});

You cannot POST files via AJAX like you have your code now.

This is how you can upload files using javascript and way better option:

PHP:

<?php
$fileName = $_FILES['afile']['name'];
$fileType = $_FILES['afile']['type'];
$fileContent = file_get_contents($_FILES['afile']['tmp_name']);
$dataUrl = 'data:' . $fileType . ';base64,' . base64_encode($fileContent);
$json = json_encode(array(
  'name' => $fileName,
  'type' => $fileType,
  'dataUrl' => $dataUrl,
  'username' => $_REQUEST['username'],
  'accountnum' => $_REQUEST['accountnum']
));
echo $json;
?>

HTML:

<!DOCTYPE html>
<!--
Copyright 2012 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
     http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Author: Eric Bidelman (ericbidelman@chromium.org)
-->
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
<title>xhr.send(FormData) Example</title>
</head>
<body>

<input type="file" name="afile" id="afile" accept="image/*"/>

<script>
document.querySelector('#afile').addEventListener('change', function(e) {
  var file = this.files[0];
  var fd = new FormData();
  fd.append("afile", file);
  // These extra params aren't necessary but show that you can include other data.
  fd.append("username", "Groucho");
  fd.append("accountnum", 123456);
  var xhr = new XMLHttpRequest();
  xhr.open('POST', 'handle_file_upload.php', true);

  xhr.upload.onprogress = function(e) {
    if (e.lengthComputable) {
      var percentComplete = (e.loaded / e.total) * 100;
      console.log(percentComplete + '% uploaded');
    }
  };
  xhr.onload = function() {
    if (this.status == 200) {
      var resp = JSON.parse(this.response);
      console.log('Server got:', resp);
      var image = document.createElement('img');
      image.src = resp.dataUrl;
      document.body.appendChild(image);
    };
  };
  xhr.send(fd);
}, false);
</script>
<!--[if IE]>
<script src="http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js"></script>
<script>CFInstall.check({mode: 'overlay'});</script>
<![endif]-->
</body>
</html>

Quick example taken from: https://gist.github.com/ebidel/2410898