3

I have looked into many posts on this subject so please do not mark it as duplicate as there are no straight answers provided. But if you truly believe that I may have missed something, which provides cross-browser support (IE8+ too) do indicate which one and then mark it as duplicate.

I want to use JQuery AJAX to post files and some text data and access that info in PHP on the server side using $_FILES and $_POST. I am able to do so without AJAX. The problem is when I start using AJAX.

Here is a simple example:

HTML:

  <form id="upload_form" method="POST" enctype="multipart/form-data">
       <input type="text"/>
       <input type="file"/>
       <button type="submit">Submit</button>
  </form>

JAVASCRIPT:

   var ser_data = $('#upload_form').serialize();

 ...on submit... {
 ...
   upload_promise = $.ajax({
    url: 'upload1.php',  
    dataType: 'html',
    type: 'POST',
    data: ser_data,
   });
 ...
  }

Well, we all know that .serialize will serialize only the text fields input and file is not readable by JS, etc. I am not trying to do anything fancy here. I just need a mechanism to access $_FILES and $_POST in PHP on the server side with the file name and the text data entered on the client side. The actual form has more fields (more file and text types) but this is the crux of the problem.

2 Answers 2

4

To send files and post data trough ajax, you should use a FormData object.

https://developer.mozilla.org/docs/XMLHttpRequest/FormData

var fd = new FormData();

var myFileInput = $(" ... "); //adapt to access your file input
var files = myFileInput[0].files ;

// The loop is there to handle file inputs with multiple files
for(var i = 0, c = files.length ; i<c ; i++){
    var blob = new Blob(files[i]);
    var fileAccessName = "myFiles_"+i ; 
    fd.append(fileAccessName, blob, files[i].name);
}

// You can also send simple data along your files
fd.append('otherData', $("...").val());


$.ajax({
    url: ... , //the form's target
    data: fd,
    processData: false,
    type: 'POST',
    success: function(rep){
        // ...
    }
}
// since we are sending the form trough jQuery, you should also add a ev.preventDefault() to your .submit(function(ev){}) callback
Sign up to request clarification or add additional context in comments.

5 Comments

Will try your solution too. Do you have any comments on the relative easier one above? I have upvoted your answer. Is this cross-browser?
From what I can read on the jQuery doc, .serialize don't handle properly "file" inputs. api.jquery.com/serialize "Data from file select elements is not serialized". I recognise my answer is more complicated, but it allows you greater control over what you send (for example by checking some values) You can find cross-browser informations on the MDN - support from IE 10, Opera 12, Chrome 7, FF 4
I am going through the link you sent. I will go through it, understand it and test it. Any browser issues here? IE 8, for example?
Unfortunately older versions of browsers (such as IE 8) do not allow high control other files trough JS.
I am accepting your answer because it is technically correct and I do not have a better option. I did find a iframe trick though but have not tested it yet. Thanks again.
2

If you submit (meaning the browser event) a form, you aren't using AJAX anymore.

  • Change your button to type="button" instead of type="submit".
  • Change your Javascript from on submit ... on a form element to on click ... on the button.
  • Give your <input>s each a name.
  • Add a success() and failure() callback to alert the user that it worked or failed (and for your own debugging).

HTML

<form id="uploadForm" enctype="multipart/form-data">
     <input name="theText" id="theText" type="text" />
     <input name="theFile" id="theFile" type="file" />
     <input type="button" name="send" id="send" value="Submit" />
</form>

jQuery

var serData = $('#uploadForm').serialize();

$('#send').on('click', function(e) {
    uploadPromise = $.ajax({
        url: 'upload1.php',  
        dataType: 'html',
        type: 'POST',
        data: serData,
        success: function() {
            alert('It worked.');
        },
        failure: function(xhr, res, err) {
            console.log(xhr);
            console.log(res);
            console.log(err);
        }
    });
});

9 Comments

And this is cross-browser? Very simple to understand indeed. I have upvoted it for now. Will certainly accept the answer after trying it out and seeing what else is coming. Strange that all the other posts on this subject make it look so complicated.
As long as you're using a version of jQuery lower than 2.x, yes cross-browser is the name of the game.
Most likely you'll need to add a contentType: '...' to match what it is you expect the file to be.
@Samir yes FormData is a nice new addition to XMLHTTP2 I would utilize that. Good answer by that user.
I'll continue researching it cuz there's gotta be something staring us in the face that we just haven't remembered.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.