dragenter()
드롭 영역에 진입할 때로 preventDefault()
를 호출할 필요가 없다.
dragover()
드래그 중인 항목이 영역 위에 있을 때 브라우저의 기본 동작을 preventDefault()
로 막고 사용자 정의 동작을 적용한다.
dragleave()
드래그 중인 항목이 영역을 빠져나갈 때로, 추가적인 인터페이스 표시 등의 작업을 하려면 preventDefault()
를 호출하지 않는다.
drop()
파일이나 데이터를 해당 영역으로 드롭할 때 브라우저의 기본 처리를 막고 사용자 정의 동작을 적용하기 위해 preventDefault()
를 호출한다.
drop 이벤트가 두번 발생하는 문제를 해결하기 위해서는 상위요소로 해당 이벤트를 전달하지 않고 자신만 이벤트를 감지하도록
event.stopPropagation()
을 사용해야 한다.
readAsDataURL()
, createObjectURL
두 가지 모두 브라우저에서 로컬 파일을 읽을 때 사용하는 방법으로 파일 미리보기에 주로 사용된다.
FileReader
객체를 통해 Blob, File 데이터를 base64 형식으로 읽어서 변환시킨다.
이 문자열을 <img>
의 src
에 넣어주면 된다.
pdf의 경우, PDF.js 라이브러리를 추가 사용해 구현 가능하다.
public fileUpload(file: any) {
const reader = new FileReader();
const previewDiv = this.preview.nativeElement;
if (file.type.match('image.*')) {
reader.onload = (event: ProgressEvent<FileReader>) => {
const img = document.createElement('img');
this.upload = event.target?.result as string;
img.src = event.target?.result as string;
img.alt = file.name;
previewDiv.appendChild(img);
}
reader.readAsDataURL(file);
}
else if (file.type === 'application/pdf') {
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@4.0.269/build/pdf.worker.mjs';
reader.onload = (e: ProgressEvent<FileReader>) => {
const typedarray = new Uint8Array(e.target?.result as ArrayBuffer);
pdfjsLib.getDocument(typedarray).promise.then((pdf: any) => {
const totalPageCount = pdf.numPages;
for (let pageNumber = 1; pageNumber <= totalPageCount; pageNumber++) {
pdf.getPage(pageNumber).then((page: any) => {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const viewport = page.getViewport({ scale: 1 });
canvas.height = viewport.height;
canvas.width = viewport.width;
const renderContext = {
canvasContext: context,
viewport: viewport,
};
page.render(renderContext).promise.then(() => {
previewDiv.appendChild(canvas);
});
});
}
}).catch((error: any) => {
console.error('Error rendering PDF: ', error);
});
}
reader.readAsArrayBuffer(file);
}
createObjectURL()
메서드는 Blob 객체를 가지고 고유한 URL을 생성할 수 있다.
브라우저 창을 닫을 때까지 유지되고 그 전에 해제하기 위해서는 revokeObjectURL()
을 호출해야 한다.
public fileUpload(file: any) {
const reader = new FileReader();
const previewDiv = this.preview.nativeElement;
if (file.type.match('image.*')) {
const img = document.createElement('img');
img.src = URL.createObjectURL(file);
previewDiv.appendChild(img);
}
else if (file.type === 'application/pdf') {
...
const pdfUrl = URL.createObjectURL(file);
pdfjsLib.getDocument(pdfUrl).promise.then((pdf: any) => {
...
})
}
메모리
문자열을 사용하는 readAsDataURL()
메소드와 달리, 포인터를 사용하는 createObjectURL()
은 메모리를 덜 사용한다.
속도
비동기식으로 작동하는 readAsDataURL()
메소드와 달리, createObjectURL()
은 동기식으로 작동하며 즉시 임시 URL을 생성하고 blob에 바인딩한다.
https://dev-gorany.tistory.com/254
https://inpa.tistory.com/entry/%EB%93%9C%EB%9E%98%EA%B7%B8-%EC%95%A4-%EB%93%9C%EB%A1%AD-Drag-Drop-%EA%B8%B0%EB%8A%A5
https://velog.io/@kykim/readAsDataURL-vs-createObjectURL
https://cdn.jsdelivr.net/npm/pdfjs-dist@4.0.269/build/