상세 컨텐츠

본문 제목

외부파일 드래그 앤 드롭1(File Drag and Drop)

자바스크립트

by e7e 2023. 12. 18. 16:41

본문

파일업로드 구현시  클라이언트 사이드에서 input type=file 만을 사용해서 만드는 거슨

기능적으로는 문제 업스낭 시대적 흐름상 쪼메 마니 없어보인당.(ㅠㅠ)

기본적으로 사용자가 필요한 파일을 바로 마우스로 드래그 드롭할 수 있도록

해주는 거슨 이젠 기본이라 해도 과언이 아닐 꼬시당.

그럼 기본을 해보장!!!~

항상 그렇진 않지만 역시 넘 쉽당. 말이나 글로는 쪼메 길어진당

 

세세하고 세세하게 알고자 한다면 아래 링크를 추천하낭

https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API

단순 파일 드래그 앤 드롭을 구현하기 위해 다 읽어야 하는 거슨 

피로도가 만만치 않으닝, 요기서 필요한 것만 확인해 보장!

 

일단 파일 드래그 앤 드랍에 대응하는 브라우져의 기본동작을 확인하기 위해

아래 소스를 복사/붙여넣기로 start.html을 맹글고 꼬옥 서버 위에서 괘니 실행해 보장

 

start.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>E7E Drag Drop</title>
    <style>
        #wrapper {
            width: 350px;
        }

        #preview {
            width: 100%;
            height: 300px;
            border: 2px solid pink;
            background-image: url("https://blog.kakaocdn.net/dn/bvQO1s/btraInYH9xW/oekuwou6IKTnzIHKD40ykK/img.png");
            background-size: 110% 110%;
            background-position: -20px -20px;
        }

        #list {
            width: 100%;
            min-height: 160px;
            border: 2px solid black;
        }
    </style>
</head>

<body>
    <h1>외부파일 끌다노킹 이해</h1>
    <div id="wrapper">
        <div id="preview"></div>
        <div id="list">
            <h4>리스트</h4>
            <hr>
        </div>
    </div>
    </script>
</body>

</html>

 

실행되었다면 파일탐색기를 열어서 이미지 파일 암거나, 마우스로 끌어다 놓아보장

어떤 일이 벌어지는강? 브라우져가 새 탭에서 이미지를 그냥 열어버린당!(ㅠㅠ)

그렇당, 브라우져는 이미지 파일을 그냥 새 탭으로 여는 기능을 내장(Built-In)하고 있당.

드래그 앤 드롭을 직접 처리하기 위해서 먼저 이 내장기능을 막아야만 한당.

요걸 막기 위해서는 dragover와 drop 이벤트에 event.preventDefault()를 써야 한당.

(파란신호등에 건널목 건너야하는 그런 규칙과 같당. 따지지 말장!)

 

id=preveiw div태그에 ondragover="f_over()" ondrop="f_drop()"를 추가하고,

아래 소스처럼 script태그에 f_over, f_drop 함수를 추가하장!

<body>
    <h1>외부파일 끌다놓깅 이해</h1>
    <div id="wrapper">

        <div id="preview" ondragover="f_over()" ondrop="f_drop()">
        </div>
        <div id="list">
            <h3>리스트</h3>
            <hr>
        </div>
    </div>
    <script>
        const myPreview = document.querySelector("#preview");
        const myList = document.querySelector("#list");

        //브라우져가 지원하는 파일 자동으로 여는 거 막기 위함
        function f_over() {
            event.preventDefault();
            event.stopPropagation();
        }


        //브라우져가 지원하는 파일 자동으로 여는 거 막기 위함
        function f_drop() {
            event.preventDefault();
            event.stopPropagation();
        }
     </script>
</body>

 

이제 다시 이전 처럼 외부 파일을 id=preview Div태그 위에 끌어다 놓아보장!(엥?)

아무일도 일어나지 않음을 알 수 있당!(오켕?,기본기능을 막아내었당!)

 

허지만 기뻐서 흥분하여 방정스런 댄스를 남발하기엔 너무나도 이르당.

id=preview  div태그 바깥쪽 아무데나 외부 이미지파일을 끌어다 놓아보면

브라우져가 해당 파일을 새 탭에서 여는 도루묵 상황이 있음이 좌절스럽당.

요것도 막아줘야만 분명 사용자가 기뻐할거시당.

쉽당. 아래 코드를 script태그 안에 넣어주기만 하면 된당!

        // Drop 영역외에 파일 끌어다 놓았을 때 브라우져 동작막깅
        window.addEventListener("dragover", function () {
            event.preventDefault();
        });

        window.addEventListener("drop", function () {
            event.preventDefault();
        });

 

의미가 느껴지는강?

브라우져 최상위 객체인 window의 dragover와 drop 이벤트의 기본 기능도 마가버렸당.

이제 다시 테스트해보면 외부파일을 어디에 끌어다 놓아도 

브라우져는 해당파일을 새탭에서 열지 않는당!(다행이당!)

여기에는 왜? event.stopPropagation()을 쓰지 않았을깡? 왱? 생각해보장!!

 

이제 기본 준비는 끝났고, 하려던 핵심을 하장.

우리가 원했던 건 id=preview  Div태그위에서 마우스버튼을 놓아버릴때  drop이벤트가 

발생하므로, 우린 drop이벤트에 연결시킨 f_drop 함수에 필요한 일을 해주기만 하면 된당.

 

input type=file을 이용해서 preview(미리보기)기능을 구현할 능력을 갖추었다는 

전제로 여기서 테스트와 기능 추가/변형이 용이하도록 전체 소스를 붙인다.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>E7E Drag Drop</title>
    <style>
        #wrapper {
            width: 350px;
        }

        #preview {
            width: 100%;
            height: 300px;
            border: 2px solid pink;
            background-image: url("https://blog.kakaocdn.net/dn/bvQO1s/btraInYH9xW/oekuwou6IKTnzIHKD40ykK/img.png");
            background-size: 110% 110%;
            background-position: -20px -20px;
        }

        #list {
            width: 100%;
            border: 2px solid black;
        }
    </style>
</head>

<body>
    <h1>외부파일 끌다노킹 이해</h1>
    <div id="wrapper">

        <div id="preview" ondragover="f_over()" ondrop="f_drop()">
        </div>
        <div id="list">
            <h3>리스트</h3>
            <hr>
        </div>
    </div>
    <script>
        const myPreview = document.querySelector("#preview");
        const myList = document.querySelector("#list");

        //브라우져가 지원하는 파일 자동으로 여는 거 막기 위함
        function f_over() {
            event.preventDefault();
            event.stopPropagation();
        }

        //브라우져가 지원하는 파일 자동으로 여는 거 막기 위함
        function f_drop() {
            event.preventDefault();
            event.stopPropagation();

            // 마우스로 끌어온 파일, 일단 1개만
            let v_file = event.dataTransfer.files[0];

            // 파일 읽어주는 아저씨 생성, 사람은 바이너리 파일을 못 읽음
            let v_fileReader = new FileReader();
            // 끌어온 파일 읽으라고 지시 
            v_fileReader.readAsDataURL(v_file);
            // 파일 내용을 다 읽었다면, load이벤트 발생(비동기)
            // 읽은 결과는 result속성에 담기게 된당.
            v_fileReader.onload = function () {
                myPreview.innerHTML = "";  // 이전 내용 클리엉
                let v_img = document.createElement("img");
                v_img.setAttribute("src", v_fileReader.result);
                v_img.style.width = "100%";
                v_img.style.height = "100%";

                // checkbox와 text를 가진 div 맹글어서 추강!
                let fileDetail = document.createElement("div");
                let chkBox = document.createElement("input");
                chkBox.type = "checkbox";
                chkBox.value = v_file.name;

                let txtBox = document.createElement("input");
                txtBox.type = "text";
                txtBox.readOnly = true;
                txtBox.style.border = "none";
                txtBox.value = v_file.name;

                fileDetail.appendChild(chkBox);
                fileDetail.appendChild(txtBox);
                fileDetail.appendChild(document.createElement("br"));

                myPreview.appendChild(v_img);
                myList.appendChild(fileDetail);

            }

        }

        // Drop 영역외에 파일 끌어다 놓았을 때 브라우져 동작막깅
        window.addEventListener("dragover", function () {
            event.preventDefault();
        });

        window.addEventListener("drop", function () {
            event.preventDefault();
        });


    </script>
</body>

</html>

 

위 소스를 실행해서 요런저런 파일들을 파일탐색기에서 끌어다 id=preview Div 태그 위에

놓으면, 대략 아래 그림과 같은 결과를 손에 쥐게 될 거시당.

소스를 찬찬히 들여다 보면서 생각하는 시간을 갖는 것은 단순 암기로는 얻을 수 없는

까마득히 깊고 넓은 내공을  여지없이 당신에게 선물할 거시당. 

 

핵심은  event.dataTransfer.files(제공되는 속성) 안에 사용자가 마우스로 끌고 온 파일정보들

담겨 있다는 거시당. 꼬옥 console.log를 찌거서 누느로 확인하는 시간을 갖도록 하장.

 

아쉽지만  첨부한 소스에는 체크박스를 넣기만 했지, 일단 소스의 기럭지를 적당히 유지하기 위해

체크박스의 체크/해제와 관련된 기능은 암것도 넣지 않았당.

 

체크박스를 이용해서 최종적으로 체크된 파일만을 upload하는 기능은 

AJAX를 이용하는가?/하지 않는가?에 따라 길이 많이 달라지고, 소스도 마니 달라지닝

요 담에 알아보도록 하장.~~

 

만약 만에 하나, input type=file을 이용한 이미지 파일 미리보기(preview)기능 구현에 어려움이

있다면 간단히 모름이라 댓글 달아주삼!~~

별수 없디용 별도 글로 써야지용~~~ (^-^)

 

 

 

 

사랑한다는 말을 남발한당.

그 사람에게만...

 

좋아한다는 말을  남발한당.

친구가 되고 픈  맘을 줘버린 그들에게만...

 

하트 이모티콘을 남발한당.

말동무가 되어 준  인연이 만나 준 그들에게...

 

감사를 쉴새없이 마구 남발한당.

안 외롭게, 안 공허하게 찰나에도

함께 해 준 그 모든 웃음과 눈물에....

 

남발하고 남발하고 남발 해보지만

정작 차 오름은 항상 넘친 적이 없이

사이 사이 끼어 든 오해와 착각만이 넘칠 준비당.

 

남발로 오해를 산다면...

오해가 풀릴까 모를 두려움에 떤다면..

지체없이 미안하다 말하장!

미안함은 남발되지 않고 진솔해야 한당

 

https://www.youtube.com/watch?v=KDx-qhwirQQ

 

관련글 더보기