From a55f0df5170aa59081fb322780e01b73c6f083fa Mon Sep 17 00:00:00 2001 From: hanyiseo2 Date: Sun, 23 Jul 2023 23:06:23 +0900 Subject: [PATCH 1/3] admin-imgUrl --- package-lock.json | 219 +++++++++++++++++++++++++++++++----- package.json | 4 +- src/app.ts | 13 ++- src/config/config.js | 40 +++++++ src/config/multerConfig.ts | 16 +++ src/config/s3Config.ts | 10 ++ src/controllers/Admin.ts | 109 +++++++++++++++++- src/service/ImageService.ts | 44 +++++++- 8 files changed, 419 insertions(+), 36 deletions(-) create mode 100644 src/config/multerConfig.ts create mode 100644 src/config/s3Config.ts diff --git a/package-lock.json b/package-lock.json index 1b0ab305..f43fb667 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@babel/preset-env": "^7.16.11", "@babel/preset-typescript": "^7.16.7", "@opensearch-project/opensearch": "^1.2.0", - "aws-sdk": "^2.1101.0", + "aws-sdk": "^2.1418.0", "babel-plugin-module-resolver": "^4.1.0", "body-parser": "^1.20.1", "chai": "^4.3.6", @@ -34,6 +34,7 @@ "lodash": "^4.17.21", "mongoose": "^6.4.6", "morgan": "^1.10.0", + "multer": "^1.4.5-lts.1", "mysql2": "^2.3.3", "node-cron": "^3.0.2", "parseurl": "^1.3.3", @@ -59,6 +60,7 @@ "@types/lodash": "^4.14.180", "@types/mocha": "^9.1.0", "@types/morgan": "^1.9.3", + "@types/multer": "^1.4.7", "@types/node": "^17.0.45", "@types/node-cron": "^3.0.2", "@types/sinon": "^10.0.15", @@ -2252,6 +2254,15 @@ "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, + "node_modules/@types/multer": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", + "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, "node_modules/@types/mysql": { "version": "2.15.21", "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.21.tgz", @@ -2693,6 +2704,11 @@ "node": ">= 8" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -2782,9 +2798,9 @@ } }, "node_modules/aws-sdk": { - "version": "2.1207.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1207.0.tgz", - "integrity": "sha512-UDNYNeWw9ATbz+pH4lI3AUQgnmK3RwowCrXmW+lVV0bZYo+efiB/LEWQKe0nZK9K2h1LxZYihIih9dOvaGme/w==", + "version": "2.1418.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1418.0.tgz", + "integrity": "sha512-6WDMJQAWKwVt+44+61c/SAXKpUSwToqBMeaqizhEe3GN8TWfxMc9RfCnsYIIwS+L+5hedmKC5oc6Fg2ujs8KUQ==", "dependencies": { "buffer": "4.9.2", "events": "1.1.1", @@ -2795,7 +2811,7 @@ "url": "0.10.3", "util": "^0.12.4", "uuid": "8.0.0", - "xml2js": "0.4.19" + "xml2js": "0.5.0" }, "engines": { "node": ">= 10.0.0" @@ -3064,8 +3080,18 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } }, "node_modules/bytes": { "version": "3.1.2", @@ -3320,6 +3346,20 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, "node_modules/config-chain": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", @@ -5968,11 +6008,21 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/mocha": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", @@ -6260,6 +6310,23 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/mysql": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", @@ -7826,6 +7893,14 @@ "node": ">= 0.8" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -8326,6 +8401,11 @@ "node": ">= 0.6" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "node_modules/typescript": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", @@ -8763,22 +8843,33 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", "dependencies": { "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" } }, "node_modules/xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", "engines": { "node": ">=4.0" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -10460,6 +10551,15 @@ "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, + "@types/multer": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", + "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, "@types/mysql": { "version": "2.15.21", "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.21.tgz", @@ -10773,6 +10873,11 @@ "picomatch": "^2.0.4" } }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -10841,9 +10946,9 @@ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" }, "aws-sdk": { - "version": "2.1207.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1207.0.tgz", - "integrity": "sha512-UDNYNeWw9ATbz+pH4lI3AUQgnmK3RwowCrXmW+lVV0bZYo+efiB/LEWQKe0nZK9K2h1LxZYihIih9dOvaGme/w==", + "version": "2.1418.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1418.0.tgz", + "integrity": "sha512-6WDMJQAWKwVt+44+61c/SAXKpUSwToqBMeaqizhEe3GN8TWfxMc9RfCnsYIIwS+L+5hedmKC5oc6Fg2ujs8KUQ==", "requires": { "buffer": "4.9.2", "events": "1.1.1", @@ -10854,7 +10959,7 @@ "url": "0.10.3", "util": "^0.12.4", "uuid": "8.0.0", - "xml2js": "0.4.19" + "xml2js": "0.5.0" } }, "aws4": { @@ -11049,8 +11154,15 @@ "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "requires": { + "streamsearch": "^1.1.0" + } }, "bytes": { "version": "3.1.2", @@ -11245,6 +11357,17 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, "config-chain": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", @@ -13256,8 +13379,15 @@ "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } }, "mocha": { "version": "10.2.0", @@ -13482,6 +13612,20 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + } + }, "mysql": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", @@ -14650,6 +14794,11 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -15011,6 +15160,11 @@ "mime-types": "~2.1.24" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "typescript": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", @@ -15337,18 +15491,23 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", "requires": { "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" + "xmlbuilder": "~11.0.0" } }, "xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==" + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, "y18n": { "version": "5.0.8", diff --git a/package.json b/package.json index 983048ca..6f5c5315 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "@babel/preset-env": "^7.16.11", "@babel/preset-typescript": "^7.16.7", "@opensearch-project/opensearch": "^1.2.0", - "aws-sdk": "^2.1101.0", + "aws-sdk": "^2.1418.0", "babel-plugin-module-resolver": "^4.1.0", "body-parser": "^1.20.1", "chai": "^4.3.6", @@ -48,6 +48,7 @@ "lodash": "^4.17.21", "mongoose": "^6.4.6", "morgan": "^1.10.0", + "multer": "^1.4.5-lts.1", "mysql2": "^2.3.3", "node-cron": "^3.0.2", "parseurl": "^1.3.3", @@ -73,6 +74,7 @@ "@types/lodash": "^4.14.180", "@types/mocha": "^9.1.0", "@types/morgan": "^1.9.3", + "@types/multer": "^1.4.7", "@types/node": "^17.0.45", "@types/node-cron": "^3.0.2", "@types/sinon": "^10.0.15", diff --git a/src/app.ts b/src/app.ts index ca7ccc37..741a5590 100644 --- a/src/app.ts +++ b/src/app.ts @@ -10,21 +10,24 @@ import properties from '@properties'; import { logger } from '@modules/winston'; import makeMorgan from '@modules/morgan'; - import { HttpError } from '@errors'; import statusCode from '@utils/statusCode'; import { verifyTokenMiddleware, encryptPassword } from '@middleware/auth'; import { updateMonitoringToken } from '@middleware/monitoring'; import { swaggerRouter } from '@controllers/index'; import SchedulerManager from '@schedules/index'; +// import { createPerfume } from './controllers/Admin'; +import { createImageUrl, createPerfume } from './controllers/Admin'; const { swaggerUi, specs, swaggerMetadataHandler, } = require('@modules/swagger'); - import { sequelize } from './models'; +import { multerConfig } from './config/multerConfig'; +import multer from 'multer'; + sequelize.sync(); require('@utils/db/mongoose.js'); @@ -58,6 +61,12 @@ app.use( }) ); +const upload = multer({ storage: multerConfig.storage }); + +// app.use('/file',) +//router로 잡으면 upload 라는 path를 +app.post('/upload', upload.single('image'), createPerfume); + app.use('/docs', swaggerUi.serve, swaggerUi.setup(specs)); app.use(swaggerMetadataHandler); diff --git a/src/config/config.js b/src/config/config.js index 0982ef47..4915b711 100644 --- a/src/config/config.js +++ b/src/config/config.js @@ -1,3 +1,40 @@ +// const config = { +// development: { +// username: process.env.MYSQL_DEV_USERNAME as string, +// password: process.env.MYSQL_DEV_PASSWORD as string, +// database: process.env.MYSQL_DEV_DATABASE as string, +// host: process.env.MYSQL_DEV_HOST as string, +// port: parseInt(process.env.MYSQL_DEV_PORT as string, 10), +// dialect: process.env.MYSQL_DEV_DIALECT as string, +// timezone: '+09:00', +// logging: false, +// s3AccessKey: process.env.AWS_ACCESS_KEY_ID as string, +// s3SecretKey: process.env.AWS_SECRET_ACCESS_KEY as string, +// bucketName: process.env.AWS_BUCKET_NAME as string, +// }, +// test: { +// username: process.env.MYSQL_TST_USERNAME as string, +// password: process.env.MYSQL_TST_PASSWORD as string, +// database: process.env.MYSQL_TST_DATABASE as string, +// host: process.env.MYSQL_TST_HOST as string, +// port: parseInt(process.env.MYSQL_DEV_PORT as string, 10), +// dialect: process.env.MYSQL_TST_DIALECT as string, +// timezone: '+09:00', +// logging: false, +// }, +// production: { +// username: process.env.MYSQL_PRD_USERNAME as string, +// password: process.env.MYSQL_PRD_PASSWORD as string, +// database: process.env.MYSQL_PRD_DATABASE as string, +// host: process.env.MYSQL_PRD_HOST as string, +// port: parseInt(process.env.MYSQL_DEV_PORT as string, 10), +// dialect: process.env.MYSQL_PRD_DIALECT as string, +// timezone: '+09:00', +// logging: false, +// }, +// }; + +// export default config; module.exports = { development: { username: process.env.MYSQL_DEV_USERNAME, @@ -8,6 +45,9 @@ module.exports = { dialect: process.env.MYSQL_DEV_DIALECT, timezone: '+09:00', logging: false, + s3AccessKey: process.env.AWS_ACCESS_KEY_ID, + s3SecretKey: process.env.AWS_SECRET_ACCESS_KEY, + bucketName: process.env.AWS_BUCKET_NAME, }, test: { username: process.env.MYSQL_TST_USERNAME, diff --git a/src/config/multerConfig.ts b/src/config/multerConfig.ts new file mode 100644 index 00000000..d30950ae --- /dev/null +++ b/src/config/multerConfig.ts @@ -0,0 +1,16 @@ +import { Request } from 'express'; +import multer from 'multer'; +type FileNameCallback = (error: Error | null, filename: string) => void; + +export const multerConfig = { + storage: multer.diskStorage({ + destination: 'perfumes/', + filename: function ( + req: Request, + file: Express.Multer.File, + cb: FileNameCallback + ) { + cb(null, file.originalname); + }, + }), +}; diff --git a/src/config/s3Config.ts b/src/config/s3Config.ts new file mode 100644 index 00000000..fc819b38 --- /dev/null +++ b/src/config/s3Config.ts @@ -0,0 +1,10 @@ +import AWS from 'aws-sdk'; +import config from './config'; + +const storage: AWS.S3 = new AWS.S3({ + accessKeyId: config.development.s3AccessKey, + secretAccessKey: config.development.s3SecretKey, + region: 'ap-northeast-2', +}); + +export default storage; diff --git a/src/controllers/Admin.ts b/src/controllers/Admin.ts index 03c1e8c4..d549f192 100644 --- a/src/controllers/Admin.ts +++ b/src/controllers/Admin.ts @@ -26,6 +26,9 @@ import { ListAndCountDTO } from '@src/data/dto'; import IngredientCategoryService from '@src/service/IngredientCategoryService'; import { DuplicatedEntryError } from '@src/utils/errors/errors'; import * as Hangul from 'hangul-js'; +import ImageService from '@src/service/ImageService'; +import multer from 'multer'; +import { multerConfig } from '../config/multerConfig'; let Admin: AdminService = new AdminService(); let Perfume: PerfumeService = new PerfumeService(); let Ingredient: IngredientService = new IngredientService(); @@ -441,6 +444,28 @@ export const createIngredientCategory: RequestHandler = async ( } }; +// export const imageUrlCreationHandler: RequestHandler = async ( +// req: Request, +// res: Response +// ): Promise> => { +// if (!req.file) +// return res +// .status(StatusCode.BAD_REQUEST) +// .json(new SimpleResponseDTO('NULL_VALUE')); + +// const fileLocation = createImageUrl(req.file); +// return res.json({ +// fileLocation, +// }); +// }; + +export async function createImageUrl( + file: Express.Multer.File +): Promise { + const fileLocation: string = await ImageService.uploadImagefileToS3(file); + return fileLocation; +} + /** * @swagger * /admin/perfumes: @@ -480,12 +505,33 @@ export const createIngredientCategory: RequestHandler = async ( * type: object * x-swagger-router-controller: Admin */ +// const upload = multer({ storage: multerConfig.storage }); + export const createPerfume: RequestHandler = async ( req: Request, res: Response ) => { - const { name, englishName, brandIdx, abundanceRate, Notes, imageUrl } = - req.body; + console.log(req.file); + // const createImageUrl: Response | any = async ( + // req: Request, + // res: Response + // ) => { + // if (!req.file) + // return res + // .status(StatusCode.BAD_REQUEST) + // .json(new SimpleResponseDTO('NULL_VALUE')); + // const fileData: Express.Multer.File = req.file; + // console.log('GET THE FILE DATA'); + // console.log(fileData); + // await ImageService.uploadImagefileToS3(fileData); + // return res.status(StatusCode.OK); + // }; + if (!req.file) + return res + .status(400) + .json({ error: 'cannot find file from the request' }); + const imageUrl = await createImageUrl(req.file); + const { name, englishName, brandIdx, abundanceRate, Notes } = req.body; try { await Perfume.create( name, @@ -655,3 +701,62 @@ export const createBrand: RequestHandler = async ( } } }; + +/** + * @swagger + * /admin/Ingredient: + * post: + * tags: + * - admin + * summary: 재료 추가 + * description: 재료 추가 + * operationId: createIngredient + * produces: + * - application/json + * parameters: + * - name: body + * in: body + * required: true + * schema: + * type: object + * properties: + * name: + * type: string + * responses: + * 200: + * description: success + * schema: + * type: object + * properties: + * message: + * type: string + * 400: + * description: 요청 실패 + * 409: + * description: 같은 이름의 카테고리가 존재할 때 + * schema: + * type: object + * x-swagger-router-controller: Admin + */ +export const createIngredient: RequestHandler = async ( + req: Request, + res: Response +) => { + const { name, seriesIdx, Category } = req.body; + try { + await IngredientCategory.create(name); + res.status(StatusCode.OK).json({ + message: '성공', + }); + } catch (e: any) { + if (e instanceof DuplicatedEntryError) { + res.status(StatusCode.CONFLICT).json( + new ResponseDTO(MSG_EXIST_DUPLICATE_ENTRY, false) + ); + } else { + res.status(StatusCode.BAD_REQUEST).json( + new SimpleResponseDTO(e.message) + ); + } + } +}; diff --git a/src/service/ImageService.ts b/src/service/ImageService.ts index 4bcbcc76..075e4bf0 100644 --- a/src/service/ImageService.ts +++ b/src/service/ImageService.ts @@ -1,4 +1,11 @@ import S3FileDao from '@src/dao/S3FileDao'; +import config from '../config/config'; +import fs from 'fs'; +import AWS from 'aws-sdk'; +import { + DuplicatedEntryError, + FailedToCreateError, +} from '@src/utils/errors/errors'; class ImageService { s3FileDao: S3FileDao; @@ -21,6 +28,41 @@ class ImageService { return [defaultImage]; } -} + static async uploadImagefileToS3( + fileData: Express.Multer.File + ): Promise { + try { + console.log('Inside the Service'); + const fileContent: Buffer = fs.readFileSync(fileData.path); + + const storage: AWS.S3 = new AWS.S3({ + accessKeyId: process.env.AWS_ACCESS_KEY_ID, + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, + region: 'ap-northeast-2', + }); + console.log('Inside the Service2'); + + const params: { + Bucket: string; + Key: string; + Body: Buffer; + } = { + Bucket: config.development.bucketName as string, + Key: fileData.originalname, + Body: fileContent, + }; + console.log('Inside the Service3'); + + const result = await storage.upload(params).promise(); + console.log(result.Location); + return result.Location; + } catch (err: Error | any) { + if (err.parent?.errno === 1062) { + throw new DuplicatedEntryError(); + } + throw new FailedToCreateError(); + } + } +} export default ImageService; From 9ae3a5ec0a82edae9478086bfeb8da54f4a67ffe Mon Sep 17 00:00:00 2001 From: hanyiseo2 Date: Thu, 27 Jul 2023 00:43:52 +0900 Subject: [PATCH 2/3] POST admin/ingredient - create ingredient --- src/app.ts | 9 +-- src/config/config.js | 37 ---------- src/config/multerConfig.ts | 3 +- src/controllers/Admin.ts | 112 +++++++++++++++++-------------- src/dao/IngredientDao.ts | 11 +++ src/dao/PerfumeDao.ts | 15 ++++- src/service/IngredientService.ts | 19 ++++++ src/service/PerfumeService.ts | 17 +++-- 8 files changed, 121 insertions(+), 102 deletions(-) diff --git a/src/app.ts b/src/app.ts index 741a5590..3d5c2b66 100644 --- a/src/app.ts +++ b/src/app.ts @@ -16,9 +16,7 @@ import { verifyTokenMiddleware, encryptPassword } from '@middleware/auth'; import { updateMonitoringToken } from '@middleware/monitoring'; import { swaggerRouter } from '@controllers/index'; import SchedulerManager from '@schedules/index'; -// import { createPerfume } from './controllers/Admin'; -import { createImageUrl, createPerfume } from './controllers/Admin'; const { swaggerUi, specs, @@ -54,6 +52,7 @@ const corsOptionsDelegate: CorsOptionsDelegate = function ( app.use(cors(corsOptionsDelegate)); app.use(bodyParser.json({ limit: '5mb' })); +const upload = multer({ storage: multerConfig.storage }); app.use( makeMorgan((message: string) => { @@ -61,11 +60,7 @@ app.use( }) ); -const upload = multer({ storage: multerConfig.storage }); - -// app.use('/file',) -//router로 잡으면 upload 라는 path를 -app.post('/upload', upload.single('image'), createPerfume); +app.use(upload.single('file')); app.use('/docs', swaggerUi.serve, swaggerUi.setup(specs)); diff --git a/src/config/config.js b/src/config/config.js index 4915b711..5265bd5d 100644 --- a/src/config/config.js +++ b/src/config/config.js @@ -1,40 +1,3 @@ -// const config = { -// development: { -// username: process.env.MYSQL_DEV_USERNAME as string, -// password: process.env.MYSQL_DEV_PASSWORD as string, -// database: process.env.MYSQL_DEV_DATABASE as string, -// host: process.env.MYSQL_DEV_HOST as string, -// port: parseInt(process.env.MYSQL_DEV_PORT as string, 10), -// dialect: process.env.MYSQL_DEV_DIALECT as string, -// timezone: '+09:00', -// logging: false, -// s3AccessKey: process.env.AWS_ACCESS_KEY_ID as string, -// s3SecretKey: process.env.AWS_SECRET_ACCESS_KEY as string, -// bucketName: process.env.AWS_BUCKET_NAME as string, -// }, -// test: { -// username: process.env.MYSQL_TST_USERNAME as string, -// password: process.env.MYSQL_TST_PASSWORD as string, -// database: process.env.MYSQL_TST_DATABASE as string, -// host: process.env.MYSQL_TST_HOST as string, -// port: parseInt(process.env.MYSQL_DEV_PORT as string, 10), -// dialect: process.env.MYSQL_TST_DIALECT as string, -// timezone: '+09:00', -// logging: false, -// }, -// production: { -// username: process.env.MYSQL_PRD_USERNAME as string, -// password: process.env.MYSQL_PRD_PASSWORD as string, -// database: process.env.MYSQL_PRD_DATABASE as string, -// host: process.env.MYSQL_PRD_HOST as string, -// port: parseInt(process.env.MYSQL_DEV_PORT as string, 10), -// dialect: process.env.MYSQL_PRD_DIALECT as string, -// timezone: '+09:00', -// logging: false, -// }, -// }; - -// export default config; module.exports = { development: { username: process.env.MYSQL_DEV_USERNAME, diff --git a/src/config/multerConfig.ts b/src/config/multerConfig.ts index d30950ae..b2c384ae 100644 --- a/src/config/multerConfig.ts +++ b/src/config/multerConfig.ts @@ -1,4 +1,3 @@ -import { Request } from 'express'; import multer from 'multer'; type FileNameCallback = (error: Error | null, filename: string) => void; @@ -6,7 +5,7 @@ export const multerConfig = { storage: multer.diskStorage({ destination: 'perfumes/', filename: function ( - req: Request, + _req: any, file: Express.Multer.File, cb: FileNameCallback ) { diff --git a/src/controllers/Admin.ts b/src/controllers/Admin.ts index d549f192..290b4c89 100644 --- a/src/controllers/Admin.ts +++ b/src/controllers/Admin.ts @@ -27,8 +27,6 @@ import IngredientCategoryService from '@src/service/IngredientCategoryService'; import { DuplicatedEntryError } from '@src/utils/errors/errors'; import * as Hangul from 'hangul-js'; import ImageService from '@src/service/ImageService'; -import multer from 'multer'; -import { multerConfig } from '../config/multerConfig'; let Admin: AdminService = new AdminService(); let Perfume: PerfumeService = new PerfumeService(); let Ingredient: IngredientService = new IngredientService(); @@ -444,21 +442,6 @@ export const createIngredientCategory: RequestHandler = async ( } }; -// export const imageUrlCreationHandler: RequestHandler = async ( -// req: Request, -// res: Response -// ): Promise> => { -// if (!req.file) -// return res -// .status(StatusCode.BAD_REQUEST) -// .json(new SimpleResponseDTO('NULL_VALUE')); - -// const fileLocation = createImageUrl(req.file); -// return res.json({ -// fileLocation, -// }); -// }; - export async function createImageUrl( file: Express.Multer.File ): Promise { @@ -468,7 +451,7 @@ export async function createImageUrl( /** * @swagger - * /admin/perfumes: + * /admin/perfume: * post: * tags: * - admin @@ -477,14 +460,64 @@ export async function createImageUrl( * operationId: createPerfume * produces: * - application/json - * consumes: - * - multipart/form-data * parameters: * - name: body * in: body * required: true * schema: * $ref: '#/definitions/PerfumeInput' + * responses: + * 200: + * description: success + * schema: + * type: object + * properties: + * message: + * type: string + * 400: + * description: 요청 실패 + * 409: + * description: 같은 이름의 카테고리가 존재할 때 + * schema: + * type: object + * x-swagger-router-controller: Admin + */ + +export const createPerfume: RequestHandler = async ( + req: Request, + res: Response +) => { + const { name, englishName, brandIdx, abundanceRate, Notes } = req.body; + try { + await Perfume.create(name, englishName, brandIdx, abundanceRate, Notes); + res.status(StatusCode.OK).json({ + message: '성공', + }); + } catch (e: any) { + if (e instanceof DuplicatedEntryError) { + res.status(StatusCode.CONFLICT).json( + new ResponseDTO(MSG_EXIST_DUPLICATE_ENTRY, false) + ); + } else { + res.status(StatusCode.BAD_REQUEST).json( + new SimpleResponseDTO(e.message) + ); + } + } +}; + +/** + * @swagger + * /admin/perfume/img: + * post: + * tags: + * - admin + * summary: 향수 추가 + * description: 향수 추가 + * operationId: createPerfumeImg + * consumes: + * - multipart/form-data + * parameters: * - name: file * in: formData * type: file @@ -505,42 +538,19 @@ export async function createImageUrl( * type: object * x-swagger-router-controller: Admin */ -// const upload = multer({ storage: multerConfig.storage }); -export const createPerfume: RequestHandler = async ( +export const createPerfumeImg: RequestHandler = async ( req: Request, res: Response ) => { console.log(req.file); - // const createImageUrl: Response | any = async ( - // req: Request, - // res: Response - // ) => { - // if (!req.file) - // return res - // .status(StatusCode.BAD_REQUEST) - // .json(new SimpleResponseDTO('NULL_VALUE')); - // const fileData: Express.Multer.File = req.file; - // console.log('GET THE FILE DATA'); - // console.log(fileData); - // await ImageService.uploadImagefileToS3(fileData); - // return res.status(StatusCode.OK); - // }; if (!req.file) return res .status(400) .json({ error: 'cannot find file from the request' }); const imageUrl = await createImageUrl(req.file); - const { name, englishName, brandIdx, abundanceRate, Notes } = req.body; try { - await Perfume.create( - name, - englishName, - brandIdx, - abundanceRate, - Notes, - imageUrl - ); + await Perfume.createImg(imageUrl); res.status(StatusCode.OK).json({ message: '성공', }); @@ -708,8 +718,8 @@ export const createBrand: RequestHandler = async ( * post: * tags: * - admin - * summary: 재료 추가 - * description: 재료 추가 + * summary: 향료 추가 + * description: 향료 추가 * operationId: createIngredient * produces: * - application/json @@ -722,6 +732,10 @@ export const createBrand: RequestHandler = async ( * properties: * name: * type: string + * seriesIdx: + * type: number + * categoryIdx: + * type: number * responses: * 200: * description: success @@ -742,9 +756,9 @@ export const createIngredient: RequestHandler = async ( req: Request, res: Response ) => { - const { name, seriesIdx, Category } = req.body; + const { name, seriesIdx, categoryIdx } = req.body; try { - await IngredientCategory.create(name); + await Ingredient.create(name, seriesIdx, categoryIdx); res.status(StatusCode.OK).json({ message: '성공', }); diff --git a/src/dao/IngredientDao.ts b/src/dao/IngredientDao.ts index cde4dd23..6e00f5bb 100644 --- a/src/dao/IngredientDao.ts +++ b/src/dao/IngredientDao.ts @@ -105,6 +105,17 @@ class IngredientDao { order: [['createdAt', 'desc']], }); } + + async create(name: string, seriesIdx: number, categoryIdx: number) { + return Ingredient.create({ + name, + seriesIdx, + categoryIdx, + englishName: '', + description: '', + imageUrl: '', + }); + } } export default IngredientDao; diff --git a/src/dao/PerfumeDao.ts b/src/dao/PerfumeDao.ts index 64cc894e..11120bfa 100644 --- a/src/dao/PerfumeDao.ts +++ b/src/dao/PerfumeDao.ts @@ -446,8 +446,7 @@ class PerfumeDao { englishName: string, brandIdx: number, abundanceRate: number, - Notes: Array, - imageUrl: string + Notes: Array ) { await sequelize.transaction(async (transaction) => { const created = await Perfume.create( @@ -456,7 +455,7 @@ class PerfumeDao { englishName, brandIdx, abundanceRate, - imageUrl, + imageUrl: '', story: '', volumeAndPrice: '', }, @@ -470,6 +469,16 @@ class PerfumeDao { return created; }); } + + async createImg(imageUrl: string | any) { + const created = await Perfume.update( + { + imageUrl, + }, + { where: {} } + ); + return created; + } } export default PerfumeDao; diff --git a/src/service/IngredientService.ts b/src/service/IngredientService.ts index 3fa56af7..e4d975ad 100644 --- a/src/service/IngredientService.ts +++ b/src/service/IngredientService.ts @@ -9,6 +9,10 @@ import { PagingDTO, } from '@dto/index'; import { Op } from 'sequelize'; +import { + DuplicatedEntryError, + FailedToCreateError, +} from '@src/utils/errors/errors'; const LOG_TAG: string = '[Ingredient/Service]'; @@ -79,7 +83,22 @@ class IngredientService { }; }); return new ListAndCountDTO(count, perfumesWithCategory); + } + async create(name: string, seriesIdx: number, categoryIdx: number) { + try { + return await this.ingredientDao.create( + name, + seriesIdx, + categoryIdx + ); + } catch (err: Error | any) { + if (err.parent.errno === 1062) { + throw new DuplicatedEntryError(); + } + + throw new FailedToCreateError(); + } } } diff --git a/src/service/PerfumeService.ts b/src/service/PerfumeService.ts index 98ce6e38..116156bd 100644 --- a/src/service/PerfumeService.ts +++ b/src/service/PerfumeService.ts @@ -479,8 +479,7 @@ class PerfumeService { englishName: string, brandIdx: number, abundanceRate: number, - Notes: Array, - imageUrl: string + Notes: Array ) { try { return await perfumeDao.create( @@ -488,8 +487,7 @@ class PerfumeService { englishName, brandIdx, abundanceRate, - Notes, - imageUrl + Notes ); } catch (err: Error | any) { if (err.parent?.errno === 1062) { @@ -498,6 +496,17 @@ class PerfumeService { throw new FailedToCreateError(); } } + + async createImg(imageUrl: string) { + try { + return await perfumeDao.createImg(imageUrl); + } catch (err: Error | any) { + if (err.parent?.errno === 1062) { + throw new DuplicatedEntryError(); + } + throw new FailedToCreateError(); + } + } } export default PerfumeService; From dec68df7131f99b7377f0738eabde199d1ba8d39 Mon Sep 17 00:00:00 2001 From: hanyiseo2 Date: Wed, 16 Aug 2023 01:34:01 +0900 Subject: [PATCH 3/3] perfume-addImage --- src/controllers/Admin.ts | 10 ++++++++-- src/dao/PerfumeDao.ts | 4 ++-- src/service/ImageService.ts | 16 +++------------- src/service/PerfumeService.ts | 4 ++-- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/controllers/Admin.ts b/src/controllers/Admin.ts index 290b4c89..791e5a4b 100644 --- a/src/controllers/Admin.ts +++ b/src/controllers/Admin.ts @@ -522,6 +522,11 @@ export const createPerfume: RequestHandler = async ( * in: formData * type: file * description: uploaded file + * - name: perfumeIdx + * in: query + * required: true + * type: integer + * format: int64 * responses: * 200: * description: success @@ -543,14 +548,15 @@ export const createPerfumeImg: RequestHandler = async ( req: Request, res: Response ) => { - console.log(req.file); if (!req.file) return res .status(400) .json({ error: 'cannot find file from the request' }); const imageUrl = await createImageUrl(req.file); + const perfumeIdx: number = Number(req.query.perfumeIdx); + try { - await Perfume.createImg(imageUrl); + await Perfume.createImg(imageUrl, perfumeIdx); res.status(StatusCode.OK).json({ message: '성공', }); diff --git a/src/dao/PerfumeDao.ts b/src/dao/PerfumeDao.ts index 11120bfa..5beb3061 100644 --- a/src/dao/PerfumeDao.ts +++ b/src/dao/PerfumeDao.ts @@ -470,12 +470,12 @@ class PerfumeDao { }); } - async createImg(imageUrl: string | any) { + async createImg(imageUrl: string | any, perfumeIdx: number) { const created = await Perfume.update( { imageUrl, }, - { where: {} } + { where: { perfumeIdx } } ); return created; } diff --git a/src/service/ImageService.ts b/src/service/ImageService.ts index 075e4bf0..6a09cee8 100644 --- a/src/service/ImageService.ts +++ b/src/service/ImageService.ts @@ -1,12 +1,11 @@ import S3FileDao from '@src/dao/S3FileDao'; import config from '../config/config'; import fs from 'fs'; -import AWS from 'aws-sdk'; import { DuplicatedEntryError, FailedToCreateError, } from '@src/utils/errors/errors'; - +import storage from '../config/s3Config'; class ImageService { s3FileDao: S3FileDao; @@ -33,29 +32,20 @@ class ImageService { fileData: Express.Multer.File ): Promise { try { - console.log('Inside the Service'); const fileContent: Buffer = fs.readFileSync(fileData.path); - const storage: AWS.S3 = new AWS.S3({ - accessKeyId: process.env.AWS_ACCESS_KEY_ID, - secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, - region: 'ap-northeast-2', - }); - console.log('Inside the Service2'); - + const keyWithPrefix = `perfumes/${fileData.originalname}`; const params: { Bucket: string; Key: string; Body: Buffer; } = { Bucket: config.development.bucketName as string, - Key: fileData.originalname, + Key: keyWithPrefix, Body: fileContent, }; - console.log('Inside the Service3'); const result = await storage.upload(params).promise(); - console.log(result.Location); return result.Location; } catch (err: Error | any) { if (err.parent?.errno === 1062) { diff --git a/src/service/PerfumeService.ts b/src/service/PerfumeService.ts index 116156bd..72676847 100644 --- a/src/service/PerfumeService.ts +++ b/src/service/PerfumeService.ts @@ -497,9 +497,9 @@ class PerfumeService { } } - async createImg(imageUrl: string) { + async createImg(imageUrl: string, perfumeIdx: number) { try { - return await perfumeDao.createImg(imageUrl); + return await perfumeDao.createImg(imageUrl, perfumeIdx); } catch (err: Error | any) { if (err.parent?.errno === 1062) { throw new DuplicatedEntryError();