on
[NodeJS] Multer를 이용해 파일 ElasticSearch에 등록하기
[NodeJS] Multer를 이용해 파일 ElasticSearch에 등록하기
728x90
https://minu0807.tistory.com/111
이 글의 2번째 목표에 해당하는 글입니다.
우선 엘라스틱에 데이터를 넣기 위해 만든 인덱스의 맵핑 정보.
file_content : 파일 바이너리 값
file_mk_dt : 파일 등록일
file_name : 파일명
file_size : 파일 사이즈
여기서 알아두어야 할게 file_content 필드에 store 옵션을 줬고, excludes에도 넣어주었는데.
해당 필드는 바이너리 값이라 파일 형태에 따라 값이 엄청 클 수도 있기 때문에
별도의 처리를 하지 않으면 데이터를 조회하거나 특정 이벤트를 할 때 문제가 생기는 경우가 있다.
특히 search를 할 때 출력할 필드를 지정하지 않고 그냥 search를 하게 되면 엄청난 양의 데이터가 불러와 지기 때문에 문제가 생긴다.
그래서 store 옵션을 주고 exludes 처리를 해두었다.
반드시 주의해야할 부분이다.
이렇게 처리하면 일반적으로 search를 할 때 해당 필드는 불러오지 않고 특정 옵션을 사용해야 검색이 가능하다.
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-store.html
이제 express
먼저 multer가 없다면 설치를 해야한다.
npm install multer
설치가 됐으면 아래와 같이 작성
const multer = require('multer'); const storage = multer.memoryStorage(); //파일을 메모리에 Buffer 객체로 저장함 const upload = multer({ storage: storage}); //파일을 메모리에 Buffer 객체로 저장함 // const upload = multer({dest: aRoot + '/api/files/'}); //파일을 저장할 폴더
multer를 사용할 때 파일 정보를 메모리 상에 버퍼로 저장을 해둔 뒤 처리를 할 것이냐, 따로 파일로 내부에 생성할 것이냐 방법이 여러 가지였는데, 난 storage 방식으로 처리했다.
메모리 방식으로 파일을 받았을 때 출력되는 정보는 이렇다.
{ 09:57:24 fieldname: 'file', originalname: 'ts_ai_result-2021-ntm-hits.json', encoding: '7bit', mimetype: 'application/json', buffer: , size: 361258 }
파일로 저장하는 방식일 때는 이렇다.
{ 09:58:29 fieldname: 'file', originalname: 'ts_ai_result-2021-ntm-hits.json', encoding: '7bit', mimetype: 'application/json', destination: 'C:\\smw\\minu_vuejs\\project_1\\web/api/files/', filename: '83061b6f744f794254cee8b781ce0c5b', path: 'C:\\smw\\minu_vuejs\\project_1\\web\\api\\files\\83061b6f744f794254cee8b781ce0c5b', size: 361258 }
https://github.com/expressjs/multer/blob/master/doc/README-ko.md
multer에 대한 자세한 정보는 여기를 참고.
이제 받은 파일을 등록하는 방법
router.post('/file_upload', upload.single('file'), async (req, res) => { const file_info = req.file; });
upload.single('file') 이 부분을 추가해주면 된다. single로 하면 1개의 파일만 받을 수 있고, array로 하면 여러 개를 받아서 처리할 수 있다.
이 전 글에서 작성했던,
저 formData의 key 값과 똑같은 값 file을 upload.single 안에 넣어주면 된다.
그리고
받은 정보도 확인하기 위해선 위처럼 똑같은 값으로 req뒤에 작성하면 정보를 확인할 수 있다.
그리고 엘라스틱에 넣기 위해 파일 정보를 바이너리로 변경해주어야 하는데
const fileContent = file_info.buffer.toString('base64');
이렇게 하면 된다.
전체적인 소스
router.post('/file_upload', upload.single('file'), async (req, res) => { console.log('/api/v1/file/file_upload'); let rt = {}; try { const file_info = req.file; const fileName = file_info.originalname; const fileSize = file_info.size; const file_mk_dt = moment().format('YYYY-MM-DD HH:mm:ss'); const fileContent = file_info.buffer.toString('base64'); const data = { file_name : fileName, file_size : fileSize, file_content : fileContent, file_mk_dt : file_mk_dt } const rs = await es_client.index({ index: index_name, type : '_doc', body: data }); Log.info(rs); rt.error = false; rt.result = rs; } catch (err) { Log.error(err); rt.error = true; rt.msg = 'err'; rt.result = err.message; } res.send(rt); });
정상적으로 등록되는 걸 확인할 수 있고, cerebro를 통해 저장된 데이터를 보면 이렇다.
파일 여러 개를 등록하는 소스
router.post('/file_multi_upload', upload.array('files'), async (req, res) => { console.log('api/v1/file/file_multi_upload'); let rt = {}; const files_info = req.files; try { let bulk = []; for(let item of files_info) { const fileName = item.originalname; const fileSize = item.size; const file_mk_dt = moment().format('YYYY-MM-DD HH:mm:ss'); const fileContent = item.buffer.toString('base64'); const data = { file_name : fileName, file_size : fileSize, file_content : fileContent, file_mk_dt : file_mk_dt } bulk.push({"index": {"_index": index_name, "_type": "_doc"}}); bulk.push(data); } let rs; if (bulk.length > 0) { rs = await es_client.bulk({ body: bulk, refresh: 'wait_for' }) Log.info(rs); } rt.error = false; rt.result = rs; } catch (err) { Log.error(err); rt.error = true; rt.msg = 'err'; rt.result = err.message; } res.send(rt); })
bulk 방식으로 작성했다.
반응형
from http://minu0807.tistory.com/112 by ccl(A) rewrite - 2021-11-20 19:00:35