[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