Έχω ένα πρόβλημα με την αποστολή ενός αρχείου σε ένα PHP-script από την πλευρά του διακομιστή χρησιμοποιώντας την jQuery's ajax-function.
Είναι δυνατόν να λάβω τη λίστα αρχείων με το $('#fileinput').attr('files')
, αλλά πώς είναι δυνατόν να στείλω αυτά τα δεδομένα στον διακομιστή; Ο πίνακας που προκύπτει ($_POST
) στο php-script από την πλευρά του διακομιστή είναι 0 (NULL
) όταν χρησιμοποιείται το file-input.
Ξέρω ότι είναι δυνατό (αν και δεν βρήκα μέχρι τώρα λύσεις jQuery, μόνο κώδικα Prototye (http://webreflection.blogspot.com/2009/03/safari-4-multiple-upload-with-progress.html)).
Αυτό φαίνεται να είναι σχετικά καινούργιο, οπότε μην αναφέρετε ότι το ανέβασμα αρχείων θα ήταν αδύνατο μέσω XHR/Ajax, γιατί σίγουρα λειτουργεί'ς.
Χρειάζομαι τη λειτουργικότητα στο Safari 5, το FF και το Chrome θα ήταν ωραία αλλά δεν είναι απαραίτητα.
Ο κώδικάς μου προς το παρόν είναι: Ο κώδικας μου είναι ο εξής:
$.ajax({
url: 'php/upload.php',
data: $('#file').attr('files'),
cache: false,
contentType: 'multipart/form-data',
processData: false,
type: 'POST',
success: function(data){
alert(data);
}
});
Ξεκινώντας από τον Safari 5/Firefox 4, είναι πιο εύκολο να χρησιμοποιήσετε την κλάση FormData
:
var data = new FormData();
jQuery.each(jQuery('#file')[0].files, function(i, file) {
data.append('file-'+i, file);
});
Έτσι τώρα έχετε ένα αντικείμενο FormData
, έτοιμο να σταλεί μαζί με το XMLHttpRequest.
jQuery.ajax({
url: 'php/upload.php',
data: data,
cache: false,
contentType: false,
processData: false,
method: 'POST',
type: 'POST', // For jQuery < 1.9
success: function(data){
alert(data);
}
});
Είναι απαραίτητο να ορίσετε την επιλογή contentType
σε false
, αναγκάζοντας την jQuery να μην προσθέσει μια επικεφαλίδα Content-Type
για εσάς, διαφορετικά, η συμβολοσειρά ορίου θα λείπει από αυτήν.
Επίσης, πρέπει να αφήσετε τη σημαία processData
σε false, διαφορετικά, η jQuery θα προσπαθήσει να μετατρέψει τα FormData
σας σε συμβολοσειρά, πράγμα που θα αποτύχει.
Μπορείτε τώρα να ανακτήσετε το αρχείο στην PHP χρησιμοποιώντας:
$_FILES['file-0']
(Υπάρχει μόνο ένα αρχείο, το file-0
, εκτός αν έχετε καθορίσει το χαρακτηριστικό multiple
στην είσοδο του αρχείου σας, οπότε οι αριθμοί θα αυξάνονται με κάθε αρχείο).
Χρησιμοποιώντας το FormData emulation για παλαιότερα προγράμματα περιήγησης
var opts = {
url: 'php/upload.php',
data: data,
cache: false,
contentType: false,
processData: false,
method: 'POST',
type: 'POST', // For jQuery < 1.9
success: function(data){
alert(data);
}
};
if(data.fake) {
// Make sure no text encoding stuff is done by xhr
opts.xhr = function() { var xhr = jQuery.ajaxSettings.xhr(); xhr.send = xhr.sendAsBinary; return xhr; }
opts.contentType = "multipart/form-data; boundary="+data.boundary;
opts.data = data.toString();
}
jQuery.ajax(opts);
Δημιουργία FormData από μια υπάρχουσα φόρμα
Αντί για χειροκίνητη επανάληψη των αρχείων, το αντικείμενο FormData μπορεί επίσης να δημιουργηθεί με τα περιεχόμενα ενός υπάρχοντος αντικειμένου φόρμας:
var data = new FormData(jQuery('form')[0]);
Χρησιμοποιήστε έναν εγγενή πίνακα της PHP αντί για έναν μετρητή
Απλά ονομάστε τα στοιχεία του αρχείου σας με τον ίδιο τρόπο και τελειώστε το όνομα σε παρένθεση:
jQuery.each(jQuery('#file')[0].files, function(i, file) {
data.append('file[]', file);
});
$_FILES['file']
θα είναι τότε ένας πίνακας που θα περιέχει τα πεδία μεταφόρτωσης αρχείων για κάθε αρχείο που μεταφορτώνεται. Στην πραγματικότητα προτείνω αυτή τη λύση σε σχέση με την αρχική μου λύση, καθώς είναι απλούστερη στην επανάληψη.
Ήθελα απλώς να προσθέσω κάτι στη σπουδαία απάντηση του Raphael's. Να πώς μπορείτε να κάνετε την PHP να παράγει το ίδιο $_FILES
, ανεξάρτητα από το αν χρησιμοποιείτε JavaScript για την υποβολή.
Φόρμα HTML:
<form enctype="multipart/form-data" action="/test.php"
method="post" class="putImages">
<input name="media[]" type="file" multiple/>
<input class="button" type="submit" alt="Upload" value="Upload" />
</form>
Η PHP παράγει αυτό το $_FILES
, όταν υποβάλλεται χωρίς JavaScript: