본문 바로가기

Node.js

[Node.js] 계정관리 서버 프로젝트 2

오늘의 할 일

- 공통 응답 모듈 만들기

- 세션관리 모듈 만들기(클라이언트가 요청하는 모든 API(로그인 제외)헤더에 토큰 있는지 검사하는 모듈 만들기)

- 파일 업/다운로드 로그인한 사용자 검사 추가

 

1. 공통 응답 모듈 만들기

function success(status, message, data) {
  return {
    success: true,
    status: status,
    message: message,
    data: data,
  };
}

function fail(status, message) {
  return {
    success: false,
    status: status,
    message: message,
  };
}

module.exports = { success, fail };

 

공통으로 들어가던 응답부분을 모듈로 따로 만들어 중복으로 작성되던 코드를 줄임

 

공통 모듈 적용 전

 

공통 모듈 적용 후

 

 

2. 세션관리 모듈 만들기(클라이언트가 요청하는 모든 API(로그인 제외)헤더에 토큰 있는지 검사하는 모듈 만들기)

var UserRealm = require("../db/realm");

function session(req, res, next) {
  // 헤더에서 이메일과 토큰 추출
  const email = req.headers.email;
  const token = req.headers.token;

  if (!email || !token) {
    return res.status(401).send({ message: "이메일과 토큰을 넣어주세요." });
  }

  try {
    const user = UserRealm.objects("User").filtered(
      `email = "${email}" AND token = "${token}"`
    )[0];
    console.log(JSON.stringify(user));
    console.log(user.length);

    if (user) {
      // 사용자가 존재하고 토큰이 일치하면 인증 성공
      // 토큰 만료시간 갱신
      UserRealm.write(() => {
        user.tokenExp = new Date();
      });
      console.log("여기는 사용자가 존재하고 토큰이 일치한것");
      console.log(JSON.stringify(user));
      return user;
    } else {
      // 사용자가 없거나 토큰이 일치하지 않으면 인증 실패
      return 0;
    }
  } catch (error) {
    console.log(error);
    return 0;
  }
}

// 토큰 만료시간 확인 코드 필요
module.exports = session;

 

3. 파일 업/다운로드 로그인한 사용자 검사 추가

위에서 만든 세션 관리 모듈을 이용해서 파일 업/다운로드 실행 전 클라이언트의 헤더를 검사함

이메일, 토큰값을 확인하여 유효한 계정만 파일 업다운로드를 실행 할 수 있음

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

const multer = require("multer"); // multer 모듈: 파일 업로드를 위한 multipart/form-data 를 다루기 위한 node.js 의 미들웨어
const fs = require("fs"); // fs 모듈: 파일 시스템을 조작하는 다양한 메서드 제공
const path = require("path"); // path 모듈: 파일 및 디렉토리 경로 작업을 위한 다양한 메서드 제공

const session = require("../module/sessionModule"); // session 모듈
const response = require("../util/response"); // 공통 응답 모듈

//------------------------------ 파일 업로드 관련 설정------------------------------//

// 파일을 업로드할 uploads 폴더 생성
fs.readdir("uploads", (error) => {
  if (error) {
    console.log("uploads 폴더를 생성합니다.");
    fs.mkdirSync("uploads");
  }
});

/*
파일 업로드 처리를 위해 multer 모듈 사용

multer.diskStorage: 파일 저장 방식을 정하는 옵션

destination: 파일이 저장될 경로를 정하는 옵션
  cb: 콜백함수로 전송된 파일을 저장할 폴더를 지정하는데 사용
  첫 번째 매개변수: 에러가 발생하면 해당 에러를 전달
  두 번째 매개변수: 실제 저장할 폴더를 지정

filename: 파일의 이름을 정하는 옵션
  cb: 콜백함수로 전송된 파일을 저장할 이름을 지정하는데 사용
  첫 번째 매개변수: 에러가 발생하면 해당 에러를 전달
  두 번째 매개변수: 파일의 이름을 지정
*/

const upload = multer({
  storage: multer.diskStorage({
    // 파일 저장 경로 설정
    destination(req, file, cb) {
      cb(null, "uploads/"); // cb 콜백 함수를 통해 전송된 파일 저장 디렉토리 설정, 'uploads/' 디렉토리로 지정
    },
    // 파일 저장명 설정
    filename(req, file, cb) {
      cb(null, file.originalname);
    },
  }),
  // 파일 최대 용량
  limits: { fileSize: 5 * 1024 * 1024 },
});

//------------------------------ api 요청 ------------------------------//

/* GET 파일 업로드 */

// 단일 파일 업로드 multer.single(fileName)
router.post("/upload", upload.single("file"), function (req, res, next) {
  result = session(req, res, next);
  console.log(`result!!!! ${result}`);

  if (result) {
    console.log("단일 파일 업로드 요청");
    console.log(req.file);
    const imagePath = req.file.path;
    if (imagePath === undefined) {
      return res.status(400).send(response.fail(400, "파일이 없습니다."));
    }
    res
      .status(200)
      .send(
        response.success(200, "파일 업로드 성공", `저장경로: /${imagePath}`)
      );
  }
});

// n개 파일 업로드 multer.array(, 개수제한)
router.post("/uploads", upload.array("files", 10), function (req, res, next) {
  console.log(req.files);
  res
    .status(200)
    .send(
      response.success(200, "파일 업로드 성공", `파일개수: ${req.files.length}`)
    );
});

module.exports = router;

업로드 정상응답

업로드 비정상응답 - 헤더에 토큰 없는 경우

 

파일 다운로드

var express = require("express");
var router = express.Router(); // router 객체는 express.Router()로 만듦

const multer = require("multer");
const path = require("path");
const fs = require("fs");

const session = require("../module/sessionModule"); // session 모듈
const response = require("../util/response"); // 공통 응답 모듈

//------------------------------ api 요청 ------------------------------//

/* GET users listing. */
router.get("/download/:fileName", function (req, res, next) {
  result = session(req, res, next);

  if (result) {
    const fileName = req.params.fileName;
    const filePath = `uploads/${fileName}`;

    console.log(`fileName: ${fileName}`);
    console.log(`filePath: ${filePath}`);
    const ch = fs.existsSync(filePath);
    console.log(`파일 존재여부: ${ch}`);

    // 다운로드 요청한 파일이 존재하는지 확인
    if (fs.existsSync(filePath)) {
      // 파일의 MIME 유형 설정(이미지, pdf, txt 등)
      res.setHeader("Content-Type", getMimeType(fileName));

      // 파일의 Content-Disposition 헤더를 "inline"으로 설정하여 파일을 브라우저에서 바로 보기
      res.setHeader("Content-Disposition", "inline; filename=" + fileName);

      // 파일 스트림을 응답에 연결
      const fileStream = fs.createReadStream(filePath);
      fileStream.pipe(res);
    } else {
      res.status(404).send(response.fail(404, "파일이 존재하지 않습니다."));
    }
  }
});

//------------------------------ 메서드 ------------------------------//

// 파일 유형을 확인하고 MIME 유형을 반환해주는 메서드
function getMimeType(fileName) {
  const extname = path.extname(fileName);
  switch (extname.toLowerCase()) {
    case ".png":
      return "image/png";
    case ".jpg":
    case ".jpeg":
      return "image/jpeg";
    case ".pdf":
      return "application/pdf";
    case ".txt":
      return "text/plain";
    default:
      return "application/octet-stream";
  }
}

module.exports = router; // 라운터를 모듈로 만듦

다운로드 정상응답

 

토큰이 없는 경우 응답

'Node.js' 카테고리의 다른 글

[Node.js] 계정관리 서버 프로젝트 3  (0) 2023.11.15
[Node.js] exress 프로젝트 로그 관리 방법  (0) 2023.11.15
[Node.js] 계정관리 서버 프로젝트 1  (0) 2023.11.14
[Node.js] CommonJS 모듈  (0) 2023.11.13
[Node.js] 모듈  (0) 2023.11.13