6 yorum

PHP ile dosya upload

PHP, Programlama ~ 05 Kasım 2009 Perşembe

PHP ile dosya yüklemek aslında gayet basit ve kavraması kolay bir olay, sadece 2 şeye ihtiyacımız var; kullanıcının dosyayı seçeceği bir form, formun dosyayı göndereceği PHP sayfası. Basit bir dosya upload olayından sonra gönderilen dosyanın tipini, en büyük veya en küçük boyutunu belirlemeyi ve birden fazla dosya göndermeyi göstereceğim.
Eğer hiç anlatıma girmeden ben direkt dosyaları alayım bakarak anlarım diyorsanız buradan buyurun. Şimdi klavyenize sıkı tutunun başlıyoruz;

PHP dosya upload için form hazırlamak

Kullanıcılar tarafından dosyanın seçileceği formumuz normal bir HTML sayfası olacak. Çünki bu sayfada bir PHP kodu çalıştırmayacağız, durağan bir form içerecek, hepsi bu. Formumuza bir adet dosya gönderme elementi ve bir de gönder butonu koyacağız.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf8" />
<title>PHP ile dosya yükleme</title>
</head>
<body>
 <h2>PHP ile dosya yükleme</h2>
 <p>Lütfen gönderilecek dosyanızı seçin ve "Dosyayı gönder" butonuna basın.</p>
 <form action="gonder.php" method="post" enctype="multipart/form-data">
  <input name="dosya" type="file" size="20" />
  <input type="submit" value="Dosyayı gönder" />
 </form>
</body>
</html>

Form argümanları özellikleri:

<form action="dosyanın gönderileceği sayfa" action="gönderme metodu (post ya da get)" enctype="gönderilecek dosyanın kodlanma tipi">

Biz formumuzu gonder.php adında bir PHP sayfasına göndereceğiz yani form argümanımızda action=”gonder.php” şeklinde. Dosyayı sunucuya taşıma işlemini orada gerçekleştireceğiz.

Yukarıdaki formumuzun görüntüsü aşağıdaki gibi olacaktır:

Şimdi kullanıcı dosyasını seçip “Dosyayı gönder” dediğinde gonder.php sayfasına yönlenecektir. Biz de şimdi orada sunucuya gönderilen dosyayı kopyalayıp sitemizdeki istediğimiz dizine yerleştireceğiz.

PHP de gönderilen dosyaların verilerilerine ulaşma:

Bir PHP dosyasına form aracılığı ile dosya gönderildiğinde o sayfada gönderilen dosyaların sayısında ve gönderilen dosyaların formdaki adlarıyla $_FILES dizininde çıkarlar.

İlk olarak deneme amaçlı gonder.php dosyamızın içerisine aşağıdaki kodu ekleyerek bize hangi verilerin ulaştığını görebilirsiniz. Genel bir kavram olarak bu kafanızda bir çok şey canlandırabilir. Bize nelerin ulaşıp ulaşmadığını rahatça görebilirsiniz.

<?php print_r($_FILES); ?>

PHP den sayfamıza gönderilen dosyayı bu $_FILES değişkeni üzerinden ulaşacağız. Gönderilen dosyayı ayırmak ve ona ulaşmak için formumuzda eklediğimiz dosya gönderme elementinde yazdığımız name=”…” değerine yazdığımız isimi kullanacağız.
Biz en yukarıdaki formumuzda bu elementin adını name=”dosya” yaptığımız için PHP’de de bu dosyaya $_FILES['dosya'] dizini üzerinden ulaşacağız.

$_FILES['dosya'] dizinin bize vereceği veriler ise şunlardır:

  • $_FILES['dosya']['name']
    • yüklenen dosyanın isminini verir.
  • $_FILES['dosya']['type']
    • yüklenen dosyanın dosya tipini verir. (örneğin; JPG dosyası ise “image/jpeg”)
  • $_FILES['dosya']['tmp_name']
    • yüklenen dosyanın geçici olarak sunucuda barındığı adres.
  • $_FILES['dosya']['size']
    • yüklenen dosyanın byte (1 kilobaytın 1024 de biri) cinsinden boyutunu verir.
  • $_FILES['dosya']['error']
    • dosya yüklenmesinde bir hata gerçekleştiyse

PHP dosyamızda ilk olarak bu dizindeki veriler ile bize bir dosya gönderilip gönderilmediğini kontrol edeceğiz. Bunun içinde $_FILES['dosya'] dizininin tanımlanıp tanımlanmadığını yani “dosya” adında bir gönderim yapılıp yapılmadığına bakacağız. Eğer $_FILES['dosya'] değişkeni tanımlanmamışsa böyle bir dosya sayfaya gönderilmemiş yani ya sayfaya direkt girilmiş ya da başka bir adresden formu kullanmadan girilmiş demektir.
Bunun için PHP de değişkenin tanımlanıp tanımlanmadığını gösteren “isset()” fonksiyonunu kullanacağız.

Şimdi gonder.php dosyamıza aşağıdaki kodu ekleyerek dosya gönderilip gönderilmediğini kontrol ediyoruz:

if( ! isset($_FILES['dosya'])):
 exit('Lütfen bir dosya gönderiniz. Dosya göndermek içinde formu kullanınız.');
endif;

Şimdi bu önlemimizi aldıktan sonra 2. olarak gönderilen dosyada hata olup olmadığına bakacağız. Bunun içinde yukarıda belirttiğimiz $_FILES['dosya']['error'] dizinini kullanacağız.
Bu dizinde eğer bir hata olduysa 0 haricinde bir rakam çıkar. Bu hata rakamlarının ne anlama geldiğini anlamak için php.net’in şu sayfasını inceleyebilirsiniz.
Şimdi biz sadece hata olup olmadığına bakacağız. Bunun içinde yukarıdaki kodumuzun altına bir koşul daha ekliyoruz yani şöyle bir hal alıyor:

if( ! isset($_FILES['dosya'])):
 exit('Lütfen bir dosya gönderiniz. Dosya göndermek içinde formu kullanınız.');
endif;

if($_FILES['dosya']['error'] != 0):
 exit('Dosya gönderimi hatalı. Lütfen gönderdiğiniz dosyayı kontrol edin.');
endif;

Ve şimdide eğer buraya kadar sorun yoksa, dosya gönderilmişse, hata kodu sıfırsa yani hata yoksa dosyayı alabiliriz demek oluyor.
Dosya gönderildiğinde geçici olarak sunucuda bir temp dizinine gönderilir. Bizde hazırlamış olduğumuz PHP sayfamız sayesinde eğer dosya istediğimiz koşullarda ise onu o geçici adresinden alıp kalıcı olarak sunucumuza kopyalayacağız.

Şimdi ben hiç koşul uygulamadan direkt tüm dosya gönderimlerini yükleyen kodumuzu gösteriyorum, bu koduda üstteki koşullarımızın altına ekliyoruz:

$temp_adres = $_FILES['dosya']['tmp_name'];
$dosya_ismi = $_FILES['dosya']['name'];
$dosya_tipi = $_FILES['dosya']['type'];
$dosya_boyutu = $_FILES['dosya']['size'];

if(move_uploaded_file($temp_adres, $dosya_ismi)):
  echo $dosya_ismi . ' adlı dosyamız başarıyla yüklendi!<br/>';
  echo $dosya_boyutu . ' bayt';
else:
  echo 'Dosya taşınamadı, lütfen yazma izini olduğundan emin olun.';
endif;

Evet işte bu kadar. move_uploadded_file() fonksiyonumuz ile upload edilen yani yüklenen dosyaları direkt olarak sunucumuza taşıyoruz. Eğer dosyayı bir klasörün içerisine göndermek istiyorsakda fonksiyonumuzu şöyle değiştiriyoruz;

move_uploaded_file($temp_adres, 'yuklenenler/' . $dosya_ismi);

bu şekilde gönderilen dosyalar yuklenenler adlı klasöre gönderilecektir.

Şu noktaya kadar böyle onlarca satırlar yazmış olsakda anlattığımız içindir. Yoksa şimdi yaptığımız kodların son haline bir bakalım şimdi:

index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf8" />
<title>PHP ile dosya yükleme</title>
</head>
<body>
 <h2>PHP ile dosya yükleme</h2>
 <p>Lütfen gönderilecek dosyanızı seçin ve "Dosyayı gönder" butonuna basın.</p>
 <form action="gonder.php" method="post" enctype="multipart/form-data">
  <input name="dosya" type="file" size="20" />
  <input type="submit" value="Dosyayı gönder" />
 </form>
</body>
</html>

gonder.php

<?php
if( ! isset($_FILES['dosya'])):
 exit('Lütfen bir dosya gönderiniz. Dosya göndermek içinde formu kullanınız.');
endif;

if($_FILES['dosya']['error'] != 0):
 exit('Dosya gönderimi hatalı. Lütfen gönderdiğiniz dosyayı kontrol edin.');
endif;

$temp_adres = $_FILES['dosya']['tmp_name'];
$dosya_ismi = $_FILES['dosya']['name'];
$dosya_tipi = $_FILES['dosya']['type'];
$dosya_boyutu = $_FILES['dosya']['size'];

if(move_uploaded_file($temp_adres, 'aaa/' . $dosya_ismi)):
  echo $dosya_ismi . ' adlı dosyamız başarıyla yüklendi!<br/>';
  echo $dosya_boyutu . ' bayt';
else:
  echo 'Dosya taşınamadı, lütfen yazma izini olduğundan emin olun.';
endif;
?>

İşte PHP ile dosyayı sunucumuza upload etme yani yükleme işi bu kadardır, şimdi gelelim filitreleme işlemlerine.

Dosya yüklemede en fazla veya en az dosya boyutu belirleme:
Bunun için kodumuzun dosyayı kopyalama komutundan yani move_uploadded_file() fonksiyonunu kullanmadan önce dosya boyutunu aldığımız $dosya_boyutu değişkeni ile bir koşul ile kontrol edeceğiz, işte kodumuz:

$temp_adres = $_FILES['dosya']['tmp_name'];
$dosya_ismi = $_FILES['dosya']['name'];
$dosya_tipi = $_FILES['dosya']['type'];
$dosya_boyutu = $_FILES['dosya']['size'];

$en_buyuk_boyut =  1024 * 1024; // bu 1MB boyutuna eşittir

if($dosya_boyutu > $en_buyuk_boyut):
  exit('Dosyanın boyutu en fazla ' . round($en_buyuk_boyut/1024) . ' kb olmalıdır.');
endif;

if(move_uploaded_file($temp_adres, $dosya_ismi)):
  echo $dosya_ismi . ' adlı dosyamız başarıyla yüklendi!<br/>';
  echo $dosya_boyutu . ' bayt';
else:
  echo 'Dosya taşınamadı, lütfen yazma izini olduğundan emin olun.';
endif;

Burada dikkat etmemiz gerekn bir noktada siz burada en yüksek boyutu belirleseniz bile PHP sizin koşulunuzdan önce sunucuda tanımlanmış olan “post_max_size” ve “upload_max_filesize” informasyonlarına bakar. Bunları değiştirmek için sunucu yöneticinizle görüşmelisiniz. Eğer sunucu sizinse ya da size bu değişimleri yapmak için izin verildiyse ini_set() fonksiyonunu kullanarak bu değerleri arttırabilir ve sunucunuza büyük dosyalar gönderebilirsiniz. Bunun örneğide aşağıdaki gibidir:

ini_set('upload_max_filesize', '5M'); // bu en büyük boyut 5 mb anlamındadır
ini_set('post_max_size', '5M'); // bu da aynı şekilde yapılmalıdır.

Sakın unutmayın sunucunuza çok büyük dosyaların gönderme izninin açılması ile sunucunuza çok büyük dosyalar gönderilemey çalışılarak sisteminize hasar verilmeye çalışılabilir. BU yüzden bu değerleri fazla uçuk yapmamaya çalışın.

Dosya tipi filitreleme
Gönderilen dosyaların sadece resim olmasını ya da sadece istediğimiz dosya tipinde olmasını da belirleyebilirsiniz. Bunun içinde aynı şekilde dosyayı sunucuya kopyalama işlemimizden önce yani move_uploaded_file fonksiyonumuzdan önce aşağıdaki koşulu ekliyoruz. Örnek olarak yanlız jpeg dosyaları yüklemeye izin vermek için:

$izin_verilen_tip = 'image/jpeg';
if($dosya_tipi != $izin_verilen_tip):
  exit('Yalnızca dosya tipi ' . $izin_verilen_tip . ' olan dosyaları yükleyebilirsiniz.');
endif;

Burada dosya uzantıları yerine dosyaların mime type denilen değerlerini girmeniz gerekir. Hangi dosyanın mime tipi ne olduğunu öğrenmek için şu adrese bakabilirsiniz.

Şuana kadar yapmış olduğumuz tüm çalışmaların kodlarını indirmek için tıklayınız.

Konu hakkındaki soru, fikir, hata, vs. gibi yorumlarınızı bekliyorum.

İşte artık bir uploader dev. olmuş durumdasınız (:
Başka bir sanal serüvende görüşmek üzere hoşça kalın.

  1. yasin diyor ki:

    yeni yazılar görmek ne güzel (:

  2. tamer diyor ki:

    eline sağlık musa çok güzel yazı olmuş..

    bu arada upload yaparken güvenliğide elden bırakmamak lazım.

  3. Burak diyor ki:

    Merhaba localhost ta yaptığım yüklemeler çalışıyor. ancak ben sadece yönetim panalinden oturum açan kullanıcının dosya yüklemesine izin vermek istiyorum. bunu için nasıl bir adım izlenecek. sonucuya dosya yazma yetkisi sadece ftp kullanıcı hesabında bilindiği üzere. Yardımlarının için teşekkürler

  4. Ali BARIN diyor ki:

    @Burak, Yönetim panelinden oturum açan kullanıcıların dosya yüklemesine izin vermek istediğine göre elinde bir yönetim paneli olduğunu varsayıyorum. Buna göre kayıtlı kişilerin görebileceği bir sayfa oluşturup bu yazıdaki kodları o sayfaya uygularsan dediğin olabilir. Tabi unutmadan dosyaları yükleyeceğin dizinin chmod ‘u 777 olmalı. Eğer her kullanıcının dosyaları ayrı ayrı klasörde tutulsun istiyorsan bu biraz daha karmaşık. Bu konu hakkında apayrı bir yazı yazılabilir. :()

  5. vehbi deniz diyor ki:

    Sunucuda deniyorum ve sürekli uzantısı image/jpeg olan dosyaların yükleneceği uyarısı alıyorum.Oysa zaten yüklediğim resim jpg uzantılı.Sanırım bir hata var.

  6. Strefrextor diyor ki:

    durumu daha iyi anlamak için

    $dosya_tipi = $_FILES['dosya']['type'];

    bu satırın altına

    echo $dosya_tipi;

    yaz ve bak bakalım sunucun gönderdiğin dosyanın tipini ne olarak alıyor. Ona göre koşullarını belirleyebilirsin

© 2008 - 2009 teyt.org | rss | iletişim | wordpress