jQuery'nin ajax fonksiyonunu kullanarak sunucu tarafındaki bir PHP betiğine dosya gönderirken sorun yaşıyorum.
Dosya Listesini $('#fileinput').attr('files')
ile almak mümkün, ancak bu Veriyi sunucuya göndermek nasıl mümkün olabilir? Dosya girişi kullanıldığında sunucu tarafındaki php komut dosyasında elde edilen dizi ($_POST
) 0'dır (NULL
).
Bunun mümkün olduğunu biliyorum (ancak şimdiye kadar herhangi bir jQuery çözümü bulamadım, sadece Prototye kodu (http://webreflection.blogspot.com/2009/03/safari-4-multiple-upload-with-progress.html)).
Bu nispeten yeni gibi görünüyor, bu yüzden lütfen XHR/Ajax ile dosya yüklemenin imkansız olduğundan bahsetmeyin, çünkü kesinlikle çalışıyor.
Safari 5'teki işlevselliğe ihtiyacım var, FF ve Chrome güzel olurdu ama gerekli değil.
Şimdilik kodum şu:
$.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 ile başlayarak, FormData
sınıfını kullanmak en kolay yoldur:
var data = new FormData();
jQuery.each(jQuery('#file')[0].files, function(i, file) {
data.append('file-'+i, file);
});
Artık XMLHttpRequest ile birlikte gönderilmeye hazır bir FormData
nesneniz var.
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);
}
});
jQuery'yi sizin için bir Content-Type
başlığı eklememeye zorlayarak contentType
seçeneğini false
olarak ayarlamanız zorunludur, aksi takdirde sınır dizesi eksik olacaktır.
Ayrıca, processData
bayrağını false olarak ayarlı bırakmalısınız, aksi takdirde jQuery FormData
nızı bir dizeye dönüştürmeye çalışacak ve bu da başarısız olacaktır.
Şimdi PHP kullanarak dosyayı alabilirsiniz:
$_FILES['file-0']
(Dosya girişinizde multiple
özelliğini belirtmediyseniz, yalnızca bir dosya vardır, file-0
, bu durumda sayılar her dosyayla birlikte artacaktır).
Eski tarayıcılar için FormData emülasyonu kullanılıyor
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);
Mevcut bir formdan FormData oluşturma
Dosyaları manuel olarak yinelemek yerine, FormData nesnesi mevcut bir form nesnesinin içeriğiyle de oluşturulabilir:
var data = new FormData(jQuery('form')[0]);
Sayaç yerine PHP'ye özgü bir dizi kullanın
Dosya öğelerinizi aynı şekilde adlandırın ve adı parantez içinde bitirin:
jQuery.each(jQuery('#file')[0].files, function(i, file) {
data.append('file[]', file);
});
$_FILES['file']` daha sonra yüklenen her dosya için dosya yükleme alanlarını içeren bir dizi olacaktır. Aslında bunu benim ilk çözümüme göre tavsiye ederim çünkü yinelemesi daha kolay.
Sadece Raphael'in harika cevabına bir parça eklemek istedim. Göndermek için JavaScript kullanıp kullanmadığınıza bakılmaksızın PHP'nin aynı `$_FILES'i üretmesini nasıl sağlayacağınız aşağıda açıklanmıştır.
HTML formu:
<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, JavaScript olmadan gönderildiğinde bu $_FILES
dosyasını üretir:
Array
(
[media] => Array
(
[name] => Array
(
[0] => Galata_Tower.jpg
[1] => 518f.jpg
)
[type] => Array
(
[0] => image/jpeg
[1] => image/jpeg
)
[tmp_name] => Array
(
[0] => /tmp/phpIQaOYo
[1] => /tmp/phpJQaOYo
)
[error] => Array
(
[0] => 0
[1] => 0
)
[size] => Array
(
[0] => 258004
[1] => 127884
)
)
)
Dosyaları göndermek için Raphael'in JS'sini kullanarak aşamalı geliştirme yaparsanız...
var data = new FormData($('input[name^="media"]'));
jQuery.each($('input[name^="media"]')[0].files, function(i, file) {
data.append(i, file);
});
$.ajax({
type: ppiFormMethod,
data: data,
url: ppiFormActionURL,
cache: false,
contentType: false,
processData: false,
success: function(data){
alert(data);
}
});
... PHP'nin $_FILES
dizisi, göndermek için bu JavaScript kullanıldıktan sonra böyle görünür:
Array
(
[0] => Array
(
[name] => Galata_Tower.jpg
[type] => image/jpeg
[tmp_name] => /tmp/phpAQaOYo
[error] => 0
[size] => 258004
)
[1] => Array
(
[name] => 518f.jpg
[type] => image/jpeg
[tmp_name] => /tmp/phpBQaOYo
[error] => 0
[size] => 127884
)
)
Bu güzel bir dizi ve aslında bazı insanlar $_FILES
i dönüştürüyor, ancak ben göndermek için JavaScript kullanılıp kullanılmadığına bakılmaksızın aynı $_FILES
ile çalışmanın yararlı olduğunu düşünüyorum. İşte JS'de yapılan bazı küçük değişiklikler:
// match anything not a [ or ]
regexp = /^[^[\]]+/;
var fileInput = $('.putImages input[type="file"]');
var fileInputName = regexp.exec( fileInput.attr('name') );
// make files available
var data = new FormData();
jQuery.each($(fileInput)[0].files, function(i, file) {
data.append(fileInputName+'['+i+']', file);
});
(14 Nisan 2017 düzenlemesi: FormData() yapıcısından form öğesini kaldırdım - bu Safari'deki bu kodu düzeltti).
Bu kod iki şey yapar.
input
ad niteliğini otomatik olarak alır. Şimdi, form
putImages sınıfına sahip olduğu sürece, diğer her şey otomatik olarak halledilir. Yani, input
un herhangi bir özel isme sahip olması gerekmez.Bu değişikliklerle, JavaScript ile gönderme artık basit HTML ile gönderme ile tam olarak aynı $_FILES
dizisini üretir.
Bu işlevi okuduğum bazı bilgilere dayanarak oluşturdum.
Bunu .serialize()
kullanır gibi kullanın, bunun yerine sadece .serializefiles();
koyun.
Burada testlerimde çalışıyor.
//USAGE: $("#form").serializefiles();
(function($) {
$.fn.serializefiles = function() {
var obj = $(this);
/* ADD FILE TO PARAM AJAX */
var formData = new FormData();
$.each($(obj).find("input[type='file']"), function(i, tag) {
$.each($(tag)[0].files, function(i, file) {
formData.append(tag.name, file);
});
});
var params = $(obj).serializeArray();
$.each(params, function (i, val) {
formData.append(val.name, val.value);
});
return formData;
};
})(jQuery);