
/images/{파일명} 으로 접근 시 images 폴더 하위의 파일을 서비스한다고 할 때
/**
* 정적 파일 서비스
*/
app.use('/images', express.static('images'));
다운로드하는 API는 아래의 조건을 추가하였다.
// 1) 기본 기능을 벗어나는 순간 OPTIONS으로 handshaking을 하기 때문에 cors method에 OPTIONS 추가 해줘야한다
// 2) request에서 받은 데이터(queryString, pathVariable, payload)를 파싱하기 위해 옵션 추가
app.use(
cors({
methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE', 'OPTIONS']
}),
// querystring 파싱 (req.query)
express.urlencoded({
extended: true
}),
// request payload 파싱 (req.body)
express.json()
);
// 정적 파일 다운로드
// 1) payload body 타입 선언 (Request의 3번째 타입이 body 타입이다)
// 2) 서버가 주는 커스텀 헤더를 front에서 사용하려면 노출시켜야한다! Access-Control-Expose-Headers 꼭 설정하기
app.post(
'/download',
(
req: Request<
{},
{},
{
contType?: ContType;
contId?: number;
}
>,
res: Response
) => {
try {
if (req.body.contType === 'P') {
const target = photosParsed.find(
(item) => item.contId === req.body.contId
);
if (target && target.filePath) {
res
.status(200)
.header({
'Download-Success': 'Y',
'Access-Control-Expose-Headers': [
'Download-Success',
'Content-Disposition'
]
})
.attachment(target.fileName || target.filePath)
.download(path.join(__dirname, '..', target.filePath));
} else {
res.status(200).send(make500Response('다운로드할 이미지가 없습니다.'));
}
} else {
res.status(200).send(make500Response('컨텐츠 타입을 확인하세요.'));
}
} catch (e) {
res
.status(200)
.send(make500Response(e instanceof Error ? e.message : String(e)));
}
}
);
서버가 추가한 헤더를 axios에서 다 가져다 쓸 수 있는줄 알았는데 아니었음.
CORS 허용 목록에 포함한 헤더가 아니면 기본적으로 프론트에서는 사용할 수 없고, 서버에서 예외적으로 노출한다고 헤더에 명시해줘야한다.