IDE: Visual Studio Code
Bu örneğimizi node.js Express modülüne dayalı oluşturduk. Dosya sistemiyle etkileşme imkanı sunan fs modülü aracılığıyla, proje klasöründeki alt klasörleri ve onlar içindeki örnek metin dosyalarını listeleyecek son derece basit bir (sözde) web uygulaması oluşturduk.
Projemizin ana kod dosyadı app.js gerekli modüllerle bağlantılı nesneleri oluşturan şu komutlarla başlıyor:
const port = 3000;
const express = require("express");
const fs = require("fs");
const path = require("path");
const app = express();
Kod dosyasının bitiminde de uygulamayı yerel web sitesi (localhost) üzerinde çalıştırıp belirtilen portta dinlemeye alan şu komutlar var:
var sunucu = app.listen(port,function() {
console.log(`The Express.js sunucu çalışıyor ve ${port} portunda dinlemede.`);
});
Express modülüne dayalı uygulamamızın giriş sayfasını (yani / rotasıyla erişilen kök sayfa) oluşturan fonksiyonu aşağıdaki gibi oluşturduk:
app.get('/', (istem, cevap) => {
cevap.setHeader('Content-Type', 'text/html; charset=utf-8');
cevap.write('<h1>Dosya Tarayıcı Uygulamamıza Hoş Geldiniz.</h1>');
cevap.write('<p>Dosya listesini görmek için aşağıdaki listeden bir klasörü tıklayınız.</p>');
// Alt klasörleri listeleyecek komutlar
cevap.end();
});
Anlayacağınız gibi, bu giriş sayfasında web sunucusunun çalıştığı sistem klasörü altındaki alt klasörler listelenecek. Bunun için gerekli kodları koyu harflerle belirlediğimiz boşluğa ekleyeceğiz.
Web uygulamamız __dirname ("dirname" teriminin öncesinde iki altçizgi) global nesnesinin temsil ettiği çalışma klasörü altında kaç tane alt klasör olduğunu ve bunların kesin ad veya adreslerini bilmeyecektir. Bu nedenle, alt klasörler listesini başlangıçta bir boş dizi olarak oluşturacaktır:
let altKlasorler = [];
Sonra da dosya sistemi modülü fs aracılığıyla, çalışma klasörü içeriğindeki dosyalar listesini elde edecektir:
let dosyalar = fs.readdirSync(__dirname);
Burada bir bakıma tedbirsizlik yaptı ve bir hata durumunda önlem alamayacak veya uyarıda bulunamayacak readdirSync fonksiyonunu kullandık. Siz değerli okuyucularımız tabi ki işin doğrusunu yapacak ve hata durumda uygun gördüğünüz işlemleri yapma imkanı verecek readdir fonksiyonunu kullanacaksınız.Çalışma klasörü içeriğindeki dosyalar listesini tarayıp, klasör olduğunu belirlediğimiz öğeleri alt klasörler listesine ekleyeceğiz:
for(var i=0; i < dosyalar.length; i++) {
var dosya = dosyalar[i];
var adres = path.join(__dirname, dosya);
if(fs.statSync(adres).isDirectory()) {
altKlasorler.push(dosya);
}
}
Unutmayın, dosya sistemi modülü fs üzerinde işlem yaptığı her öğenin dosya sistemindeki adresini isteyecektir. Bunu da path modülü aracılğıyla dosya adını çalışma klasörü adresiyle birleştirerek elde ediyoruz. Uygulamamızı basit tutmak ve anlaşılır kılmak için de yine hata durumunda önlem alma imkanı vermeyen bir Sync fonksiyonu kullanıyoruz.Alt klasörler listesini geri planda bir JavaScript dizisi şeklinde oluştururken, aynı zamanda uygulamamızın giriş sayfasında da bir maddeli liste oluşturmalıyız. Bunun için yukarıdaki döngümüze koyu harflerle ayırtettiğimiz şu komutları ekliyoruz:
cevap.write('<ul>');
// Alt klasörlerin listesini dosyalar listesinden seçerek oluşturuyoruz
for(var i=0; i < dosyalar.length; i++) {
var dosya = dosyalar[i];
var adres = path.join(__dirname, dosya);
if(fs.statSync(adres).isDirectory()) {
altKlasorler.push(dosya);
cevap.write('<li><a href=' + dosya + '>' + dosya + '</li>');
}
}
cevap.write('</ul>');
Bir alt klasör olduğunu belirlenen her sistem öğesi için, kendisine işaret eden bir link (<a href=...>) de içeren bir liste öğesi (<li>...</li>) eklemiş oluyoruz.
Tekrar hatırlatalım: Klasörler dizisi ve listesi oluşturan bu komutları yukarıda boş iskeletini gösterdiğimiz giriş sayfası oluşturan fonksiyon içine ekliyoruz.Uygulamamızı şimdiye kadar eklediğimiz kodlarla çalıştırmak için Visual Studio Code geliştirme ortamının terminal penceresinde node app.js komutunu çalıştırdık. Uygulamamız aşağıdaki konsol mesajıyla çalıştığı bildiren bir teminat verdi:
user@os:~/...$ node app.js
The Express.js sunucu çalışıyor ve 3000 portunda dinlemede.
Tarayıcımızda da uygulamanın çalışma klasörü altındaki klasörlerin listesini gördük:
Giriş sayfasındaki alt klasörler listesinin her öğesinde bir de link koymuştuk. O linki (diyelim alt1 adlı klasör linkini) tıklayan bir ziyaretçi uygulama giriş sayfası altında aynı adlı bir alt sayfayı açmış olacaktır:
http://localhost:3000/alt1
Uygulamamız bu durumda, o alt klasör içeriğini listelemelidir. Fakat uygulamamız tıklanıp açılan alt klasörün adını, dolayısıyla da o alt klasöre ait alt sayfa adresini önceden bilemez. Bu nedenle, herhangi bir alt sayfa açılınca devreye girecek şu fonksiyonu ana kod dosyasına ekliyoruz:
app.get('/*', (istem, cevap) => {
let dosya = istem.url;
let adres = path.join(__dirname, dosya)
// Dosya/klasör adresi geçerli mi diye bak
if (fs.existsSync(adres)) {
// geçerli adres klasör adresiyse,
// onun dosya listesini görüntüleyecek
//fonksiyonu çağır:
if(fs.statSync(adres).isDirectory()) {
klasorGoruntule(istem, cevap);
}
else {
// Bir dosya içeriği istenmişse,
// dosya içeriğini görüntüleyecek
// fonksiyonu çağır:
dosyaGoruntule(istem, cevap);
}
}
else{
cevap.setHeader('Content-Type', 'text/html; charset=utf-8');
cevap.write('<h1>Üzgünüz!</h1>');
cevap.write('<p>İstediğiniz dosya ya da klasör bizde yok.</p>');
cevap.end();
}
});
Bu fonksiyon istem.url bilgisine bakarak, ziyaret edilen sayfa adresini belirliyor, onu içeriği görüntülecek bir dosya veya klasör gibi düşünerek, adını dosya adlı yerel değişkene atıyor.
Bundan sonra da dosya adını yine çalışma klasörü adresiyle birleştirerek, sayfa adının dosya sistemindeki adres karşılığını buluyor.
Artık çoktan anladığınız gibi, dosya sistemiyle iletişim halindeki bir web uygulamasında en dikkat etmeniz gereken nokta sunucudaki sayfa adresiyle dosya sistemindeki adresler arasındaki bağlantıları doğru kurmaktır.Artık bir sonraki adım belirlenen adresteki alt klasör içeriğini listelemek olacaktır, ama şuna da dikkat etmemiz gerekecektir: Bu basit uygulamamız klasör içeriğindeki dosyaları listelediği zaman, o dosyaların içeriğine de erişim imkanı verecektir. yani ziyaret edilen sayfa adresi bir dosyaya da karşılık gelebilir. Bu nedenle, yine dosya sistemi modülü fs'den yardım alıyor, belirlenen adresin bir klasöre mi yoksa bir dosyaya mı karşılık geldiğine bakıyor. Buna göre de farklı görüntüleme fonksiyonlarını çağırıyor.
Geçerli olmayan bir adres durumunda ise (ziyaretçi rasgele bir sayfa istemişse) duruma uygun bir uyarıyla durumdan sıyrılıyor.
Bir alt klasöre ait link tıklanmışsa, şu fonksiyon açılan sayfada o klasör içeriğindeki dosya adlarıyla, dosya linklerini de içeren bir web listesi oluşturacaktır:
function klasorGoruntule(istem, cevap) {
let klasor = istem.url;
let adres = path.join(__dirname, klasor)
cevap.setHeader('Content-Type', 'text/html; charset=utf-8');
// Klasördeki dosyaların listesini al
let dosyalar = fs.readdirSync(adres);
cevap.write('<ul>');
dosyalar.forEach((dosya) => {
cevap.write('<li><a href=' + klasor + '/' + dosya + '>'
+ dosya + '</li>');
});
cevap.write('</ul>');
cevap.end();
}
Bu döngüde uygulamamız olukça gevşek davranarak, alt klasör içeriğindeki her öğeyi bir dosya imiş gibi listeliyor. Listede daha da alt klasörler varsa beklenmeyen durumlar oluşabilir.Uygulamamız artık alıştığınız(!) gevşekliğiyle, linki tıklanarak açılan dosyanın içeriğini HTML öğeleriyle süslemeden veya web için düzenlemeden, öylesine sayfaya atmayı seçiyor:
function dosyaGoruntule(istem, cevap) {
let dosya = istem.url;
let adres = path.join(__dirname, dosya)
cevap.sendFile(adres);
}
Siz okuyucularımız gerekli kontrolleri yaparak, daha mantıklı düzenlenmiş bir sayfa oluşturabilirsiniz. Belki de bir şablon motoru (view engine) kullanarak, klasör veya dosya içeriklerini önceden oluşturduğunuz kalıplara sokarsınız.Kod dosyasının son halini aşağıdaki linkten indirebilirsiniz. Unutmayın, bu dosyayı hazır kullanmak için, önce kullandığınız IDE ile bir node.js projesi oluşturmalı ve bu projeye Express modülünü eklemelisiniz. VS Code kullanıyorsanız, kod dosyasını o alt klasöre kopyalamalı, o klasör içinde npm ile Express modülünü kurmalısınız.