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?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

RationalRabbitAuthor 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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
HTML

From novice to tech pro — start learning today.