You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

92 lines
3.9 KiB

12 months ago
  1. const express = require('express')
  2. const path = require("path");
  3. const md5 = require("md5");
  4. const multer = require("multer");
  5. const router = require('express').Router();
  6. const randomstring = require('randomstring');
  7. const fs = require("fs");
  8. /**
  9. * 사용자 파일 업로드
  10. */
  11. router.post('/attaches', async (req, res) => {
  12. // 업로드 허용 확장자
  13. const allowExt = [".csv", ".psd", ".pdf", ".ai", ".eps", ".ps", ".smi", ".xls", ".ppt", ".pptx",".gz", ".gzip", ".tar", ".tgz", ".zip", ".rar", ".bmp", ".gif", ".jpg", ".jpe",".jpeg", ".png", ".tiff", ".tif", ".txt", ".text", ".rtl", ".xml", ".xsl",".docx", ".doc", ".dot", ".dotx", ".xlsx", ".word", ".srt",".webp"];
  14. // 이미지 파일 확장자
  15. const imageExt = [".gif",".jpg",".jpe",".jpeg",".png",".tiff",".tif",".webp"]
  16. // 업로드 경로를 계산합니다.
  17. // 업로드 경로는 app/data/uploads/년도/월 이 됩니다
  18. const yearMonth = path.posix.join((new Date().getFullYear()).toString() , (new Date().getMonth() + 1).toString());
  19. const directory = path.join('data','uploads',yearMonth); // 루트 디렉토리를 기준으로 업로드 경로
  20. const uploadPath = path.join(root, 'data', 'uploads', yearMonth); // 루트 디렉토리를 포함한 업로드 경로
  21. // multer 미들웨어 설정
  22. const upload = multer({
  23. dest: uploadPath,
  24. }).array('userfile'); // 파일 필드의 이름을 지정
  25. // 디렉토리가 존재하지 않는다면, 디렉토리를 생성합니다.
  26. try {
  27. if (!fs.existsSync(uploadPath)) {
  28. // 디렉토리가 없는 경우 생성
  29. fs.mkdirSync(uploadPath, { recursive: true });
  30. }
  31. } catch (err) {
  32. console.error('디렉토리 생성 중 에러 발생:', err);
  33. return res.status(500).json({ error: 'Failed to create directory' });
  34. }
  35. const resultArray = [];
  36. // multer 미들웨어 실행
  37. upload(req, res, async (err) => {
  38. if (err) {
  39. console.error('파일 업로드 중 에러 발생:', err);
  40. return res.status(500).json({ error: '파일 업로드 실패' });
  41. }
  42. req.files.map(async (file) => {
  43. const ext = path.extname(file.originalname).toLowerCase(); // 파일의 원본이름에서 확장자를 구합니다.
  44. const originalName = file.originalname; // 파일의 원본명은 따로 저장해둡니다.
  45. // 업로드 허용 확장자인지 체크합니다.
  46. if( allowExt.indexOf(ext) < 0) {
  47. return res.status(400).json({error: '업로드가 허용되지 않는 확장자를 가진 파일이 포함되어 있습니다 : ' + ext})
  48. }
  49. let fileName = md5(`${Date.now()}_${originalName}`) + randomstring.generate(5) + ext; // 파일이름을 랜덤하게 변경합니다. 한글이나 유니코드등 사용할수 없는 문자를 처리하기 위함입니다.
  50. let filePath = path.join(uploadPath, fileName); // 파일이 업로드될 경로 +
  51. // 혹시 동일한 파일명이 존재한다면 파일명이 겹치지 않을떄까지 파일명을 계속 변경해 봅니다.
  52. while (fs.existsSync(filePath)) {
  53. fileName = md5(`${Date.now()}_${originalName}`) + randomstring.generate(5) + ext;
  54. filePath = path.join(uploadPath, fileName);
  55. }
  56. fs.renameSync( file.path, filePath )
  57. // 응답결과에 추가해줍니다.
  58. resultArray.push({
  59. file_url: path.join(path.sep, 'attaches', yearMonth, fileName),
  60. file_path: path.join(directory , fileName),
  61. original_name: originalName,
  62. isImage: imageExt.indexOf(ext) >= 0,
  63. extension: ext,
  64. mime: file.mimetype,
  65. file_size: file.size
  66. });
  67. })
  68. return res.json(resultArray);
  69. });
  70. });
  71. /**
  72. * 객체 내보내기
  73. */
  74. module.exports = router;