Submit Multipart Form with Multiple File Attachments Using jQuery, Ajax, PHP

I am revamping and old set of forms, using jQuery and Ajax for submission. My problem with this form is that it may include attachments. The user may include as many attachments as they like. As it was originally set up, the user adds a new row to a table for each attachment. I would like to keep it that way, as it is easier for the inexperienced user to understand.

The big question is how to send the the file data along with the form using jQuery and Ajax. There are, it seems, hundreds of examples on the Web, none of which address all my issues, and many of which I have tried and failed to customize for my needs, which are
  • Separate inputs for each file attachment
  • Multipart form with fields of numerous types
  • AJAX submit
  • The ability to append two text fields to the form data
  • Able to process server-side with normal HTML $_FILES variables  

Here is a brief example of the attachment section of the form:
<form id="CreditForm" name="CreditForm" method="post" enctype="multipart/form-data" accept-charset="UTF-8">
   <table class="AFormTable">
      <tr>
         <td style="width:20px;"><input type="checkbox" name="chk" /></td>
         <td>Attachment '.($i+1).':</td>
         <td><input type="file" id="SendFile1" name="SendFile[]" /></td>
      </tr>
   </table>
   <div>
      <a href="javascript:void(0)" onclick="AddRow('AttachTable')">Add Attachment</a>&nbsp;&nbsp;&nbsp;&nbsp;
      <a href="javascript:void(0)" onclick="DeleteRow('AttachTable')">Delete Selected</a>
   </div>
   <div id="UserSubmitMenu">
      <input style="width:150px;" class="SubmitButton" type="submit" name="Submit"  id="Next"   value="Next" /><br /><br />
      <input style="width:312px;" class="SubmitButton" type="submit" name="Save"    id="Save"   value="Save for later completion" />
   </div>
</form>

Open in new window

Which results in something like this:
      <tr><td>Attachment 1</td><td><input name="SendFile[]" type="file"></td></tr>
      <tr><td>Attachment 2</td><td><input name="SendFile[]" type="file"></td></tr>
      <tr><td>Attachment 3</td><td><input name="SendFile[]" type="file"></td></tr>

Open in new window

jQuery:
<script type="text/javascript">
   $(document).ready(function()
   {
      $(document).on('click', '.SubmitButton', function(e)
      {
         e.preventDefault();
         var ButtonID = $(this).attr('id');
         var Form = $('#CreditForm');
         var Valid = false;
         if(ButtonID == "Save")
         {
            var FormData = Form.serialize();
            FormData = FormData + "&Sec=Credit&Process=Save";
            Valid = true; // Validation not required
         }
         else if(ButtonID == "Next")
         {
            var FormData = Form.serialize();
            FormData = FormData + "&Sec=Credit&Process=Next";
            Valid = FormVal(); // Perform Validation
         }
         if(Valid)
         {
            $.ajax(
            {
               type: "POST",
               url: "AjaxForms.php",
               data: FormData,
               success: function(response)
               {
                  alert(response);
               }
            });
         }
      });
   });
</script>

Open in new window

My most recent attempt with jQuery to incorporate the file attachments looks like this:
<script type="text/javascript">
   $(document).ready(function()
   {
      $(document).on('click', '.SubmitButton', function(e)
      {
         e.preventDefault();
         var ButtonID = $(this).attr('id');
         var Form = $('#CreditForm');
         var Valid = false;
         if(ButtonID == "Save")
         {
            var Data = new FormData(Form)[0];
            Data.append( 'Sec', "CreditSave" );
            Data.append( 'Process', "Save" );
            Valid = true; // Validation not required
         }
         else if(ButtonID == "Next")
         {
            var Data = new FormData(Form)[0];
            Data.append( 'Sec', "CreditSave" );
            Data.append( 'Process', "Next" );
            Valid = FormVal(); // Perform Validation
         }
    
         if(Valid)
         {
            $.ajax(
            {
               url: 'Ajax-Forms.php',
               type: 'POST',
               data: Data,
               async: false,
               cache: false,
               contentType: false,
               processData: false,
               success: function (returndata)
               {
                  alert(returndata);
               }
            });    
         }
      });
   });
</script>   

Open in new window

On the PHP side, I haven't changed from my original HTML $_FILES[] form processing, and would like to keep it that way.
<?PHP
$AttachCount = count($_FILES);
if($AttachCount > 0)
{
   $Attachment = array();
   $AttachLocation = array();
   $C = count($AttachName);
   if($C > 0)
   {
      for($i=0;$i<$C;$i++)
      {
         $Attachment[]     = $AttachName[$i];
         $AttachLocation[] = $AttachPath[$i];
      }
   }
   while(list($key,$value) = each($_FILES[SendFile][name]))
   {
      if(!empty($value))
      {
         $FileName = $value;
         $FileName=str_replace(" ","_",$FileName);// Replace spaces with underscore
         $Sep1 = explode('.',$FileName);
         $AttachName = $Sep1[0].'_'.UniqueCode(6,2).'.'.$Sep1[1];
         if(@move_uploaded_file($_FILES[SendFile]['tmp_name'][$key],$AttachFolder.$AttachName))
         {
            $Uploaded=true;
            $Attachment[]     = $FileName;
            $AttachLocation[] = $AttachFolder.$AttachName;
         }
         else
         {
            $Error[] = "Attachments failed to upload!";
            if($_FILES[SendFile][size] > 20000)
            {
               $Error[] = "File size cannot be greater than 2 MB";
            }
         }
      }
   }
}
?>

Open in new window

LVL 1
RationalRabbitAsked:
Who is Participating?
 
RationalRabbitConnect With a Mentor Author Commented:
Actually, this code is correct. There were two problems - one I corrected before posting the question, but had not corrected it in my test code. On the PHP side, the variable $Attachfolder is included in a configuration file that the PHP file did not have access to.

I have looked at a great number of solutions for including file uploads in a form, and this is the most effective solution I have found. There is no restriction on file type, so, if that is preferable, it will need to be added.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.