백엔드에서 exel다운 받을 수 있게 api를 만들어주셨다.
클릭할 때 api호출해서 다운만 받으면 되는데
api 호출의 응답이 이렇게 왔다. ( 지극히 정상이다.)
어떻게 하면 이 응답을 이용해서 유저가 클릭하자마자 엑셀 다운로드가 가능하게 할 수 있을까 지금부터 살펴보자.
해결법 먼저 보자면, api를 호출할 때 headers에 responseType을 blob
으로 보내줘야 했고 받을 때도 새로운 Blob객체를 이용해서 처리를 해줘야 했다.
엑셀 다운 api 요청할 때 get과 post 두가지로 요청할 수 있는데 내가 요청하기로 되어있는 method는 get이었다.(이것은 api 문서에 적혀있었다.)
axios를 이용하여 공통 api호출 함수로 apiCall이라는 것을 만들어 사용한다고 가정하자.
export const getExcel = (authToken) => {
return apiCall(
`URL`,//api URL
'get',//api method
{},//body
{
authorization: authToken,
responseType: 'blob',
},//headers
);
};
//axios api호출할 때 headers에 responseType으로 'blob'을 주고
-------------------------------------------------
const getExcelDown = () => {
getExel(authToken).then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data], { type: response.headers['content-type'] }),);
//content-type이 application/download 로 오기 때문에 이 type으로 받으면 바로 다운로드가 실행된다. 데이터를 파싱해서 사용하진 않아도 되지만 열어주는 과정이 필요하기 때문에 a태그나 window.open이 필요하다.
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'exel_name.xlsx');
//두 번째 인자로 넣어준 것은 엑셀 파일의 기본 이름이 되겠다.
document.body.appendChild(link);
link.click();})
}
//그리고 response에서 new Blob으로 새로운 객체를 생성하여 a태그의 href로 연결해주고 click 함수를 넣어줘 바로 excel다운로드 가능하게 하였다.
이렇게 해결했다...
그럼 Blob이란 무엇일까...
언어별로 Blob에 대한 정보는 다를 수 있다. JavaScript에서 Blob(Binary Large Object, 블랍)은 이미지, 사운드, 비디오와 같은 멀티미디어 데이터를 다룰 때 사용할 수 있다고 한다.(아직 비디오, 사운드, 이미지에는 사용해보지 않았지만)
대개 데이터의 크기(Byte) 및 MIME 타입을 알아내거나, 데이터를 송수신을 위한 작은 Blob 객체로 나누는 등의 작업에 사용한다.
=> MIME type 이란? Multipurpose Internet Mail Extensions의 약자로 파일 변환을 의미한다. 처음에 이메일에 첨부된 파일을 텍스트 문자로 전환해서 이메일 시스템을 통해 전달하기 위해서 만들어졌기 때문에 이름에 Internet Mail Extensions가 들어갔다고 한다. 현재는 웹을 통해 여러형태의 파일을 전달하는데 쓰이고 있다. -> 이에 대해서는 다시 포스팅을 할 예정이다.
Blob 생성자는 새로운 Blob객체를 반환한다.
생성 시 인수로 array와 options를 받는다.
const newBlob = new Blob(array, options);
Blob 생성자의 첫번째 인수로 ArrayBuffer, ArrayBufferView, Blob(File), DOMString 객체 또는 이러한 객체가 혼합된 Array를 사용할 수 있다.
new Blob([new ArrayBuffer(data)], { type: 'video/mp4' });
new Blob(new Uint8Array(data), { type: 'image/png' });
new Blob(<div>Hello Blob!</div
, {
type: 'text/html',
endings: 'native'
});
옵션으로는 type과 endings를 설정할 수 있다.
type은 데이터의 MIME 타입을 설정하며, 기본값은 "" 이다.
endings는 \n을 포함하는 문자열 처리를 "transparent"와 "native"로 지정할 수 있으며, 기본값은 "transparent"이다.
Properties
생성자를 통해 만들어진 Blob 객체는 size, type의 속성을 가진다.
Blob { size: 38472 , type : "img/png"} // 약 38kb
size는 Blob 객체의 바이트(Byte) 단위 크기를 의미하며, type은 객체의 MIME 타입을 의미한다.
MIME 타입을 알 수 없는 경우 빈 문자열("")이 할당된다.
method
Blob 객체에서 사용할 수 있는 slice 메소드는 지정된 바이트 범위의 데이터를 포함하는 새로운 Blob 객체를 만드는 데 사용된다.
10MB 이상 사이즈가 큰 Blob 객체를 작게 조각내어 사용할 때 유용하다.
const blob = new Blob(); // 새로운blob 객체 생성
blob.slice(start, end, type);
start는 시작 범위(Byte, Number), end는 종료 범위(Byte, Number), type은 새로운 Blob 객체의 MIME 타입(String)을 지정한다.
예를들어,
// Blob 객체(blob)에서 첫 1KB의 JPG Blob 객체(chunk)를 생성
const chunk = blob.slice(0, 1024, 'image/jpeg');
Blob을 이용하여 이미지를 잘라 저장했다가 이어 붙이는 등 이용할 수 있다. 좋은 예제로
Blob에 관한 블로그 <- 이곳에 가면 확인할 수 있다.
초반에 엑셀 다운로드 하면서 window.URL.createObjectURL()을 사용하였는데, 이는 Blob 객체를 가리키는 URL을 생성하여 DOM에서 참조할 수 있게 한다.
Blob 객체를 가리키는 URL 생성을 위해서 사용하는 URL객체의 정적 메소드(Static Method)이다.
createObjectURL과 revokeObjectURL를 사용할 수 있다.
(만들어주고, 없애주는 것)
URL.createObjectURL()은 Blob 객체를 나타내는 URL를 포함한 다음과 같은 DOMString를 생성한다.
이 Blob URL은 생성된 window의 document에서만(브라우저) 유효하다.
다른 window에서 재활용할 수 없으며, URL의 수명이 한정되어 있기 때문에 file:URL과 다르게 보안 이슈에서 벗어날 수 있다.
이미지의 경우
<img src="url" alt="Blob URL Image" />
나의 경우
<a href="url"></a>
// url = window.URL.createObjectURL( new Blob([ response.data], { type: response.headers['content-type'] }), )
URL.revokeObjectURL()은 URL.createObjectURL()을 통해 생성한 기존 URL을 폐기한다.
revokeObjectURL을 통해 폐기하지 않으면 기존 URL를 유효하다고 판단하고 자바스크립트 엔진에서 GC(garbage collector) 되지 않는다.
메모리 누수를 방지하기 위해 생성된 URL을 DOM과 바인딩한 후에는 폐기하는 것이 좋다.
// Create Blob URL
const blobUrl = window.URL.createObjectURL(blob);
// Revoke Blob URL after DOM updates..
window.URL.revokeObjectURL(blobUrl);
여기까지 백엔드에서 엑셀 다운받을 수 있도록 처리해준 뒤 보내줬을 때는 이렇게 받는 방법이 있음을 포스팅 했다.
물론 프론트 단에서도 라이브러리를 이용한다던가 엑셀 내용 자체를 만들어서 엑셀형태로 다운받을 수 있는 방법이 있고 관련 포스팅이 꽤나 많았다. 멋있는 사람들..
자 이제 MIME에 대해서 다음글로🙌