브라우저에서 버튼을 클릭할 때 파일을 다운로드하게 하려면 <a href="주소" download>클릭</a>
를 많이 사용하곤 합니다. 물론 단순히 button 태그를 만들고 onclick 시 동적으로 a 태그와 download 속성을 만들어주어도 됩니다.
어쨌든 노드 쪽에서도 파일은 전송하기 위한 라우터가 필요한데요. 익스프레스 기준으로 설명드리도록 하겠습니다. 다른 프레임워크도 원리는 똑같습니다.
router.get('주소', (req, res, next) => {
const stream = fs.createReadStream('파일경로');
stream.pipe(res);
});
위 코드는 기본적인 라우터입니다. 파일을 읽어서 보낼 때는 위처럼 하거나
router.get('주소', (req, res, next) => {
res.sendFile('파일경로');
});
위처럼 하는데요. 이렇게만 하면 파일이 다운로드 되지 않고, 요청에 대한 응답에 문자열이나 버퍼 형식으로 들어있게 됩니다.
한 가지 빠뜨린 것이 있어서 그런데 코드를 다음과 같이 수정하면 다운로드가 됩니다.
router.get('주소', (req, res, next) => {
const 파일명 = 'file.ext';
res.setHeader('Content-Disposition', `attachment; filename=${파일명}`); // 이게 핵심
res.sendFile('파일경로');
});
헤더에 Content-Disposition을 넣어주는 것을 빠뜨리면 안 됩니다. 이 헤더를 브라우저가 읽고 다운로드라고 인식하거든요. 헤더 값에는 저장되길 원하는 파일명을 적어주면 됩니다.
https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Content-Disposition
또한 익스프레스에서는 더 간단하게 다음과 같이 res.download를 쓸 수 있습니다. 당연히 내부적으로 Content-Disposition 헤더를 설정해주겠죠?
router.get('주소', (req, res, next) => {
res.download('파일경로', '파일명');
});
참고로 Content-Disposition 헤더는 폼데이터를 전송할 때도 쓰입니다. Content-Disposition: form-data; 로 요청 바디에 들어 있는 경우가 많습니다.