일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Redux
- code editor
- jszip
- uint16array
- userevent_tracker
- FirebaseAnalytics
- webrtc
- Game js
- Three js
- typescript
- RouteObserver
- KakaoMap
- uint8array
- androidId
- REST API
- Prism.js
- Excel
- swagger-typescript-api
- Babel standalone
- react
- web track
- Image Resize typescript
- Three-fiber
- node
- Raycasting
- identifierForVender
- babel
- Completer
- Flutter
- methodChannel
- Today
- Total
Never give up
React - zip, unzip(Feat. JSZip) 본문
압축 파일을 다룰일이 생겨서 간단하게 예제를 만들어봤습니다
먼저 클라이언트에서 압축파일을 사용하게 됐을 때의 장점으로는
1. 클라이언트가 여러개의 파일을 다운로드 받지 않아도 된다
2. 서버가 파일 리스트를 조회 한 후 넘겨주지 않아도 된다
3. 네트워크 리소스를 적게 사용한다
4. 별도의 서버작업 없이 파일 압축이 가능하다
정도 될거 같습니다
zipUtil.ts
import { saveAs } from "file-saver";
import JSZip, { JSZipObject } from "jszip";
export const zipUtil = {
/** - extract file list from file url */
async extractFile(url: string) {
const res = await fetch(url);
const arrayBuffer = await res.arrayBuffer();
const zip = new JSZip();
const contents = await zip.loadAsync(arrayBuffer);
let fileList: JSZipObject[] = [];
for (const content of Object.values(contents.files)) {
fileList = [...fileList, content];
}
return fileList;
},
/** - zip files */
async zipFile(fileList: { name: string; file: Blob }[], fileName: string) {
const zip = new JSZip();
fileList.map((e) => {
zip.file(e.name, e.file);
});
const downloadFile = await zip.generateAsync({ type: "blob" });
saveAs(downloadFile, fileName);
},
/** - get file from url */
async getFileFromUrl(url: string) {
const res = await fetch(url);
return await res.blob();
},
};
구현한 함수는 총 3개로
1. zip파일을 받아서 압축 해제하는 부분
2. 압축하기
3. url로 부터 파일 blob형태로 가져오기
간단하게 만들어 봤습니다
해당부분을 사용하는 컴포넌트 부분에서 같이 코드를 보면 좋을거 같습니다
import { JSZipObject } from "jszip";
import React, { useState } from "react";
import Button from "src/component/button";
import { zipUtil } from "src/util/zipUitl";
import styles from "./zip.module.css";
const ZipPage = () => {
const [images, setImages] = useState<string[]>([]);
const onUnzipFile = async () => {
// public/assets/example.zip
const files = await zipUtil.extractFile("/example.zip");
let imgList: string[] = [];
// remove dir
for (const e of files.slice(1)) {
const img = await toImg(e);
imgList = [...imgList, img];
}
setImages(imgList);
};
const onDownload = async () => {
let fileList: { name: string; file: Blob }[] = [];
for (const name of ["react.svg", "node.svg"]) {
const file = await zipUtil.getFileFromUrl(`/assets/${name}`);
fileList = [...fileList, { name, file }];
}
zipUtil.zipFile(fileList, "example.zip");
};
const toImg = async (obj: JSZipObject) => {
const blob = await obj.async("blob");
// never set it as octet-stream if you want to show it in img tag
const file = new File([blob], obj.name, { type: "image/svg+xml" });
return new Promise<string>((res) => {
const reader = new FileReader();
reader.onload = () => {
res(`${reader.result}`);
};
reader.readAsDataURL(file);
});
};
return (
<div className={styles.div_main}>
<div>
<Button onClick={onUnzipFile}>Unzip</Button>
<Button onClick={onDownload}>Download</Button>
</div>
<div className={images.length === 0 ? styles.hidden : undefined}>
{images.map((e, i) => {
return <img key={`img-${i}`} width={50} height={50} src={e} />;
})}
</div>
</div>
);
};
export default ZipPage;
먼저 unZipFile부터 보면 .zip파일(이미지 파일들 압축)을 불러와서
blob형태로 로드 해준 후 File로 변환 -> 이미지로 변환 해주는 작업을 하고 있습니다
createObjectUrl이랑 FileReader부분에 대해서 장단점을 고민해본적이 있는데
createObjectUrl
1. 대용량 파일에 적합 ex) 이미지, 동영상, 음성파일
2. 메모리를 조금 더 효율적으로 사용
3. revoke를 해줘야됨
FileReader
1. base64, binary등의 데이터를 다룰때 적합
2. 대용량 파일을 불러올 때 퍼포먼스 이슈 발생 가능
3. 별도로 revoke를 안해줘도됨
해당 예제에서는 작은 svg를 사용하기에 FIleReader가 조금 더 나을거 같아서 사용해봤습니다
(revoke하기 귀찮아서..)
다음으로 download 부분을 보면
public/asset에 있는 파일들을 가져와서 압축하고 다운로드 하는 부분인데
다른 서버 파일 url을 사용할때도 동일합니다
zip에 파일을 넣을때 fileName, file(blob)형태로 들어가게 됩니다
'WEB' 카테고리의 다른 글
React - excel example(feat. XLSX) (0) | 2024.11.14 |
---|---|
React - Failed to fetch dynamically imported module (0) | 2024.08.20 |
React - code editor 3(feat. Prism.js) (1) | 2023.12.15 |
React - code editor 2 (0) | 2023.12.15 |
React - code editor 1(feat. babel standalone) (0) | 2023.12.13 |