본문 바로가기
Study

[Node.js] Excel 파일 업로드 및 다운로드 하기 (feat. Multer)

by 안자두 2024. 2. 21.

1. 계기

 

회사에서 진행 중인 프로젝트에서 여러 명의 사용자를 추가할 때, 엑셀 파일을 업로드한 후, 해당 파일 데이터를 파싱하여 사용하려고 하는 로직이 추가되었다.
프론트에서도 추가적으로 양식을 다운로드한 후, 작성된 파일을 다시 업로드하는 컴포넌트를 만들게 되었다.

로직은 크게 
1. 서버로부터 받은 파일 다운로드
2. 파일 서버로 업로드
두 가지다.

아직 서버쪽 API 개발이 완성되지 않았다고 하여, 임시로 express.js로 node.js 서버를 구현해 테스트해보았다.


2. 개발 환경

 

테스트용 서버로 express를 사용하였고, FormData 형식의 데이터를 읽기 위해 Multer를 사용할 예정이다.

기본적인 서버는 아래와 같이 세팅하였다.

// server.js
import cors from 'cors';
import express from 'express';

const app = express();
app.use(cors());

app.use(express.json());

app.listen(4000, () => {
	console.log('listening on port 4000');
});

 


3. 양식 다운로드 하기

 

기본 스타일이 적용된 엑셀 파일을 서버에서 보내주면 프론트에서 해당 파일을 다운로드할 수 있도록 한다.

먼저 코드를 보자.

import path from 'path';
const __dirname = path.resolve();

app.get('/excel', async (req, res) => {
	res.sendFile(path.join(__dirname, `./example.xlsx`));
});

esmodule로 사용할 때는 __dirname을 path로부터 정의해주어야 한다.

엑셀 파일 전송은 excel로 api get 요청을 받았을 때, rendFile로 현재 directory의 양식 excel file을 보내주었다.
__dirname을 사용해 쉽게 현재 경로를 알 수 있다.

파일에 추가 사항이 없다면, 이렇게 쉽게 전송할 수 있다.
또는, 다른 정보들을 추가해 줄 수 있다. 현재 프로젝트의 경우에는 headers에 Content-Disposition 설정으로 파일 이름을 추가해 주었다.

만약 headers에 여러 정보를 추가하였는데 프론트에서는 해당 정보가 확인할 수 없다면, Access-Control-Expose-Headers를 추가해 주자!
현재 프로젝트에서도 해당 사항 이슈로 서버 쪽에서 아래 코드를 추가해 주니 잘 되었다.

response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");

 


4. 파일 작성 후 업로드 하기

 

프론트에서는 양식을 받았으니, 작성 후 파일을 업로드를 해줄 것이다.

여기서는 업로드된 양식이 제대로 도착했는지 확인하기 위해 파일을 download라는 새 폴더를 만들어 이곳에 받은 파일을 저장해 테스트할 것이다.

해당 코드도 먼저 보자면,

// server.js
import multer from 'multer';

const upload = multer({
	storage: multer.diskStorage({
		destination: function (req, file, cb) {
			cb(null, './download/');
		},
		filename: function (req, file, cb) {
			cb(null, 'example.xlsx');
		},
	}),
});

app.post('/excel', upload.single('excelFile'), async (req, res) => {
	console.log(req.file);
	res.sendStatus(200);
});

 

가장 중요한 부분은 Multer를 사용해 FormData 형식을 받을 수 있도록 한다.

다운로드하지 않을 거라면, multer 내부 객체가 필요 없다. 하지만 나는 테스트 용으로 파일을 저장할 것이기 때문에 옵션을 추가해 주었다.

간단히 살펴보자면,
destination은 파일의 저장 경로를 지정해 주는 속성이고, filename은 말 그대로 저장될 파일의 이름을 설정해 줄 수 있는 속성이다. 
파일 경로에 해당 폴더가 없다면 에러가 나고, 파일 이름에 확장자가 명시되어 있지 않으면 확장자 없는 파일이 생성되기 때문에 이점을 주의해야 한다.

이제 post api를 살펴보자.
보통은 app.post(url, callback) 형식으로 구성되어 있겠지만, 지금은 upload라는 이름의 미들웨어 Multer를 추가해 주었다.
미들웨어는 콜백함수 전 실행된다.
현재 코드에서 미들웨어는 formData를 받아 req.file에 저장해 주는 역할을 한다.

받는 파일이 여러 개인 경우 array, 한 개인 경우 single을 사용하여 FormData를 받을 수 있다.
매개변수에는 FormData에서 지정한 파일 이름을 작성해 주면 된다.

formData.append('excelFile', this.uploadData);

프론트쪽에서 excelFile이라는 이름으로 파일을 추가했기 때문에 이 이름을 작성해 주었다.

파일이 여러 개인 경우에는 req.files에 할당되고, 한 개인 경우에는 req.file로 할당된다.
콘솔을 찍어보면 전송된 파일이 잘 찍히는 것을 확인할 수 있다.

그리고 현재 위치의 download 폴더에 example.xlsx라는 이름으로 파일이 잘 저장된 것도 확인할 수 있다!

 


REF

https://soobindeveloper8.tistory.com/866

https://github.com/expressjs/multer/blob/master/doc/README-ko.md

 

728x90