프로그래밍언어/자바스크립트

[Javascript] 파일 첨부 이미지 미리보기 기능 구현 - 코드, 예시, 설명

지이구 2022. 5. 30. 11:39

 

 

 

jsp, js, jquery 환경에서 파일 이미지 미리보기 기능 구현하기

 

 

첨부파일 기능을 개발할 때 확장자 제한, 파일명 길이 제한, 파일 사이즈 제한과 같은 기능들을 주로 구현하는데

만약 이미지 파일 업로드가 목적이라면 미리보기(Preview) 기능이 필요할 때도 있다

 

 

 

📌 기능

0. 파일 첨부

1. 확장자 제한

2. 파일 사이즈 제한

3. 파일명 길이 제한

4. 이미지 미리보기

5. 미리보기 이미지 클릭시 원본크기 팝업 

 

 

 

📌 예시

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>imgPreview</title>
    <style>
        @font-face {
            font-family: 'GangwonEdu_OTFBoldA';
            src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2201-2@1.0/GangwonEdu_OTFBoldA.woff') format('woff');
            font-weight: normal;
            font-style: normal;
        }
        html {font-family: 'GangwonEdu_OTFBoldA'}
        .uploadImg {margin:10px;margin-top:150px;}
        img#previewImg{cursor:pointer;max-height:200px; max-width:100%;display:block;}

        .filebox {display:inline-block;margin:10px;}
        .filebox label {display: inline-block; padding: 4px 8px; margin-left:5px; color: #999; font-size: inherit; line-height: normal; vertical-align: middle; border-radius: .25em; cursor: pointer; color: #fff; background-color: #895fc0; border: 1px solid #683d8b;}
        .filebox input[type="file"] {position: absolute;width: 1px;height: 1px;padding: 0;margin: -1px;overflow: hidden;clip:rect(0,0,0,0);border: 0;}
        .filebox .upload-name{display: inline-block; padding: 0.3em 0.4em; font-size: inherit; font-family: inherit; line-height: normal; vertical-align: middle; background-color: #f5f5f5; 
                                border: 1px solid #ebebeb; border-bottom-color: #e2e2e2; border-radius: .25em; -webkit-appearance: none; -moz-appearance: none; appearance: none; }
    </style>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
</head>
<body>
    <div class="uploadImg">
        <div class="filebox">
            <input class="upload-name" value="선택된 파일 없음" disabled="disabled">
            <input type="file" id="file1" class="upload-hidden" name="file1">
            <label for="file1">이미지 첨부</label> 
        </div>
        <img id="previewImg" onclick="popImage(this.src)">
    </div>
</body>
</html>

 

위의 코드는 기능 구현 테스트를 위한 샘플 html 코드이다

가독성을 위해 css가 복잡하게 적혀있지만 기능 구현과는 관련 없고 body 영역이 중요하다

filebox 안의 label은 파일 첨부를 위한 버튼의 개념이고 실제 파일이 첨부되는 곳은 input type file인 곳이다

그리고 <img id="previewImg">는 미리보기로 보여질 이미지 부분이다

 

 

아래가 스크립트에 대한 부분이다

<script>
    $(document).ready(function(){
        //파일첨부 이벤트
        $('.filebox .upload-hidden').on('change', function(){  			
            if(window.FileReader){
                var filename = $(this)[0].files[0].name;
                if(!validFileType(filename)){
                    alert("허용하지 않는 확장자 파일입니다.");
                    return false;
                }else{
                    if(!validFileSize($(this)[0].files[0])){
                        alert("파일 사이즈가 10MB를 초과합니다.");
                        return false;
                    }else{
                        if(!validFileNameSize(filename)){
                            alert("파일명이 30자를 초과합니다.");
                            return false;
                        }
                    }
                }
            } else {
                var filename = $(this).val().split('/').pop().split('\\').pop();
            }
            $(this).prev().val(filename); //input upload-name 에 파일명 설정해주기

            readImage($(this)[0]); //미리보기
        });
    });

    function validFileType(filename) {
        const fileTypes = ["png", "jpg", "jpeg"];
		return fileTypes.indexOf(filename.substring(filename.lastIndexOf(".")+1, filename.length).toLowerCase()) >= 0;
	}
	
    function validFileSize(file){
        if(file.size > 10000000){ //10MB
            return false;
        }else{
            return true;
        }
    }

    function validFileNameSize(filename){
        if(filename.length > 30){ //30자
            return false;
        }else{
            return true;
        }
    }

    //이미지 띄우기
    function readImage(input) {
	    if(input.files && input.files[0]) {
	        const reader = new FileReader();
	        reader.onload = function(e){
	            const previewImage = document.getElementById("previewImg");
	            previewImage.src = e.target.result;
	        }
	        // reader가 이미지 읽도록 하기
	        reader.readAsDataURL(input.files[0]);
	    }
	}
	
    //이미지 원본 팝업 띄우기
    function popImage(url) {
        var img = new Image();
        img.src = url;
        var img_width = img.width;
        var win_width = img.width + 25;
        var img_height = img.height;
        var win = img.height + 30;
        var popup = window.open('', '_blank', 'width=' + img_width + ', height=' + img_height + ', menubars=no, scrollbars=auto');
        popup.document.write("<style>body{margin:0px;}</style><img src='"+url+"' width='"+win_width+"'>");
    }
</script>

 

 

파일첨부 이벤트 발생시 일어나는 Validation에 대한 코드는 생략하고

이미지 파일 미리보기 기능 관련 코드만 떼어서 보면 아래와 같다

 

readImage($(this)[0]); //미리보기

//이미지 띄우기
function readImage(input) {
    if(input.files && input.files[0]) {
        const reader = new FileReader();
        reader.onload = function(e){
            const previewImage = document.getElementById("previewImg");
            previewImage.src = e.target.result;
        }
        // reader가 이미지 읽도록 하기
        reader.readAsDataURL(input.files[0]);
    }
}

 

readImage 함수를 호출하여 미리보기를 호출하는데 이 때 input file을 파라미터로 넣어준다

그래서 해당 input에 파일이 있을경우 FileReader를 선언하고

미리 만들어놓은 img태그의 src가 onload될때의 파일을 가리키도록 onload function을 작성해준 다음

reader가 파일을 읽어오도록 readAsDataURL()을 실행하는 것이다

 

 

 

 

📌 실행화면

위의 html + script를 복사하여 vscode에서 실행해본 결과이다

 

728x90
반응형