Nodejs: Sunucuya Dosya Yüklemek

Giriş

Hepinize Merhabalar👋
Bu yazımızda, nodejs altyapılı bir projemize nasıl görsel veya başka bir dosyayı yükleyip, sunucuda bir kopyasını tutacağımızı inceleyeğiz.

Bu işlemleri yaparken de dosya yükleme işlemlerini kolaylaştıran multer kütüphanesinden yardım alacağız. Hazırsanız başlayalım.

Front-end'in yazılması

Öncelikle HTML tarafında dosyayı almak için bir input ve sunucuya isteği tetiklemek için bir button ekleyelim;

<body>
    <input id="file" type="file" />
    <button id="upload">Submit</button>
</body>

Şimdi de butona tıkladıktan sonra çalışacak kodları yazalım;

<script>
document.querySelector("#upload").addEventListener("click", async () => {
    const fileInput = document.querySelector("#file");
    const formData = new FormData();
    for (let i = 0; i < fileInput.files.length; i++) {
        const file = fileInput.files[i];
        formData.append("files", file);
    }
    let response = await fetch("/upload-file", {
        method: "POST",
        body: formData,
    });
    response = await response.json();
    console.log(response);
});
</script>

Back-end'in Yazılması

  • End-point'in Eklenmesi
    Projemize upload-file adında, POST metoduna sahip bir route tanımlayalım.
router.post("/upload-file", (req, res, next) => {});

Gelen isteğe bir yanıt dönelim ve front-end'de o istekten gelen yanıtı kontrol edelim. Böylelikle butona tıklanıldığı zaman - dosya yüklenilmeden önce - herşeyin çalıştığına emin olacağız.

router.post("/upload-file", (req, res, next) => {
  res.json({ message: "upload-file is triggered" });
});

Screenshot_366
Şuana kadar herşey güzel gözüküyor🎉
Şimdi de projemize multeri entegre ederek, gelen datayı bir klasörün içerisine kaydedelim.

  • Multer'in Projeye Dahil Edilmesi
npm i multer --save

komutunu kullanarak kütüphaneyi, projemize indiriyoruz. Route'yi tanımladığımız dosyanın en üstüne gidiyoruz ve multer konfigürasyonlarını yapıyoruz.

const multer = require("multer");

const storage = multer.diskStorage({
  destination:  (req, file, cb) =>{
    cb(null, "uploads");
  },
  filename:  (req, file, cb) =>{
    cb(null, file.originalname);
  },
});

const upload = multer({ storage }).array("files");

destination: Gelen dosyanın yükleneceği yolun yapılandırıldığı fonksiyon.
filename: Gelen dosyanın isminin yapılandırıldığı fonksiyon.

Bunları yaptıktan sonra route'mizi aşağıdaki şekilde güncelliyoruz.

router.post("/upload-file", (req, res, next) => {
  console.log(req.files);
});

Örnek bir dosya yükleyip gelen req.files objesine bakalım.
Screenshot_367-1
storage kısmında tanımladığımız filename fonksiyonu, yukarıda bulunan originalname kısmındaki değeri alarak, kullanıcının yüklediği dosya ismini sunucuya klonlanacak dosyanın ismiyle eşitliyor ve böylelikle uploads klasörü altında kullanıcının yüklediği dosya klonlanmış oluyor.
Şimdi de upload işlemini yapalım ve hataları yakalamak içinde try/catch kullanalım.

router.post("/upload-file", (req, res, next) => {
  try {
    upload(req, res, (err) => {
      if (err) return res.json({ success: false, message: err.message });
      if (!req.files.length)
        return res.json({
          success: false,
          message: "Lütfen bir dosya seçiniz.",
        });
      if (err) return res.json({ success: false, message: err.message });
      res.json({ success: true, message: "Dosya başarıyla yüklendi!" });
    });
  } catch (error) {
    res.json({ success: false, message: error.message });
  }
});
  • Gelen dosyayı koşullandırma(sadece görsel vb.)
    Bunun için üstteki kodlarda biraz değişiklik yapmamız gerekiyor.
    Öncelikle koşul tanımlayalım;
const upload = multer({
  storage,
  fileFilter: (req, file, cb) => {
    if (
      file.mimetype == "image/png" ||
      file.mimetype == "image/jpg" ||
      file.mimetype == "image/jpeg"
    ) 
      cb(null, true);
    else {
      cb(null, false);
      return cb(new Error("Lütfen sadece fotoğraf yükleyiniz!"));
    }
  },
}).array("files");

fileFilter fonksiyonunu kullanarak gelen dosyanın tipine bakarak onu sunucuya yükleme/yüklememe işlemi yaptık.

Ve sonuç:
Screenshot_368

Ayrıca dosya boyutlarının istediğiniz aralıkta olması gibi diğer tüm koşullar için aşağıda bıraktığım kaynakça kısmında multer'in dokümantasyonuna bakabilirsiniz.

Not1: Hata çıkmaması için projemizin kök dizininde uploads adında bir klasör açmayı unutmayalım.
Not2: Ben projemi express-generator ile oluşturduğum için tüm yapı hazır geldi. Eğer siz elle sıfırdan yazıyorsanız body-parser kütüphanesini eklemeyi unutmayın.
Ve tüm işlemler bu kadar,
Okuduğunuz için teşekkürler görüşmek dileğiyle!🚀

Kaynakça & Kodlar

HTML KODLARI

<!DOCTYPE html>
<html lang="tr">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Deneme</title>
  </head>
  <body>
    <input id="file" type="file" />
    <button id="upload">Submit</button>
    <script>
      document.querySelector("#upload").addEventListener("click", async () => {
        const fileInput = document.querySelector("#file");
        const formData = new FormData();
        for (let i = 0; i < fileInput.files.length; i++) {
          const file = fileInput.files[i];
          formData.append("files", file);
        }
        let response = await fetch("/upload-file", {
          method: "POST",
          body: formData,
        });
        response = await response.json();
        console.log(response);
      });
    </script>
  </body>
</html>

SERVER KODLARI

const express = require("express");
const router = express.Router();
const multer = require("multer");

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, "uploads");
  },
  filename: (req, file, cb) => {
    cb(null, file.originalname);
  },
});

const upload = multer({
  storage,
  fileFilter: (req, file, cb) => {
    if (
      file.mimetype == "image/png" ||
      file.mimetype == "image/jpg" ||
      file.mimetype == "image/jpeg"
    )
      cb(null, true);
    else {
      cb(null, false);
      return cb(new Error("Lütfen sadece fotoğraf yükleyiniz!"));
    }
  },
}).array("files");

router.post("/upload-file", (req, res, next) => {
  try {
    upload(req, res, (err) => {
      if (err) return res.json({ success: false, message: err.message });
      if (!req.files.length)
        return res.json({
          success: false,
          message: "Lütfen bir dosya seçiniz.",
        });
      if (err) return res.json({ success: false, message: err.message });

      res.json({ success: true, message: "Dosya başarıyla yüklendi!" });
    });
  } catch (error) {
    res.json({ success: false, message: error.message });
  }
});

module.exports = router;
multer
Middleware for handling `multipart/form-data`.
Multer Kütüphanesi
Tolga Çağlayan

Tolga Çağlayan

En tehlikeli kelime nedir Olric? -Ama’dır efendim bana göre. Neden Olric? -Önceden söylenen her söylemi veya kelimeyi öldürür! Mesela, seni seviyorum ama. gibi.
Anonim