Programing

이미지 미리보기 스크립트 삽질

handam 2016. 6. 2. 16:18

파일업로드 이미지 미리보기 삽질

본문은 그냥 삽질한 내용의 기록이며 브라우저에서 미리보기 해결방안을 찾는 분이라면 피해가시길

음... 그냥 뻘짓을 좀 했다. 파일업로드는 아니고 input:file 에서 이미지를 미리보여주는 스크립트가 있던데 거지같은 IE 에서는 filereader 객체를 사용하려면 버전도 타고, html5 태그 지원 여부도 타고, 뭐 그렇게 타는게 많은지...

생각을 좀 했는데 이미지를 미리 보여주고자 하는 목적이 무엇인가? 이다. (기획자의 의도와는 별개로)

  • 그냥 업로드에 문제가 없는지 체크하려고..?
  • 업로드 후 어떻게 보여지는가를 확인하기 위함..?

이것도 맞고 저것도 맞을 수 있는데.. 무엇보다 사용자가 업로드 하고자 하는 이미지가 은도끼인지 금도끼인지 구분하기 위함이 가장 크지 않을까? 아니, 애초에 파일브라우저에서 확인도 안하고 사진을 선택할리 없잖은가..

IE 가 참 거지같구나를 시작으로 새삼 다시 또 계속 쭈욱 느끼며 이런 저런 생각을 했다. 결국 서버가 업로드 당해야만 하는 억울함을 풀어줄 길은 없는 것일까. 구지 업로드 후에 보여주어야 하는가?

그 때, 불현듯 파일브라우저에서 이미지를 인터넷브라우저 볼수도 있다는 생각이 스쳤고 그냥 이미지를 보여줄 수는 없는가 궁금해졌다. 인터넷브라우저에서 이미지를 보면 단순하다. 로컬이미지를 브라우저로 드래그 해서 보게 되면

URL 에는 C:\path\path\path.jpg 라고 로컬주소가 찍힐 뿐이고, 소스보기를 하면

<body><img src="file:///C:/path/path/Downloads/path.jpg"></body>

정도가 다였으니까. 라고 생각했다.

소스부터 깐다.

<input type="file" onchange="javascript:getRealPath(this);" /> <br> <!--<div id="imagePreview"></div>--> <img id="imgPreview" src="" title="img" style="width:480px;" /> <input type="text" id="real_path" /> <script type="text/javascript"> function getRealPath(obj){ obj.select(); // document.selection <-- 크로스브라우징 안됨 // document.selection.createRange().text.toString(); //이게 실행이 안된다면.... // document.selection.createRangeCollection()[0].text.toString(); //이걸로.... var val = 'file\:\/\/\/'+(document.selection.createRangeCollection()[0].text.toString()); document.getElementById('real_path').value = val; document.getElementById('imgPreview').src = val; /* val 값을 찍어보면 알겠지만 ... file://C:\path\path\path.jpg */ } </script>

input:file onchange 이벤트에 getRealPath()라는 이벤트를 걸었고 처음 난관이 IE 에서의 fakepath 문제였다. IE 에서는 파일선택시 보여지는 경로가 fakepath 로 나오는데 실제경로를 도출해야 했다. 뭐 어렵지 않게 이건 구글링으로 찾았는데 이게 또 버전을 탄다...

그리고 input:text 에 값(경로)을 찍어보면 실제 파일경로가 나오긴 하는데 이게 또... 프로토콜이 file 이다보니 일단 보안 쪽에서 뭔가 걸리는건 아닐까 싶고, 두번째로 img src 경로를 넣어주려면 역슬래시를 치환해야겠는데 슬래시(/)로 치환하려고 해도 역슬래시는 문제가 되는것이, 기본적으로 이스케이프 문자이며 다른 영소문자와 만날 때 \t, \r, \n등의 문자로 이루어질 때 개행 등의 역할을 가지는 특수한 경우라 정상적으로 인식하지를 않는다.

아니.. 모르겠다. 정규식을 이용한 패턴 조합을 만들어서 하면 될란가? 몇 가지 조합은 해봤지만 ..

이해를 돕기 위한 예를 들면,
'C:\path\path\path.jpg'.replace('\\', '\/') 을 치환하면 결과가 "C:pathpathpath.jpg" 이렇다.

구글링으로 자바스크립트 역슬래시를 기타 특문으로 정규식을 사용한 방법도 해보려고 했지만 사라진다. 그냥.. 반나절을 역슬래시 치환 때문에 이러고 뻘짓하다가 날렸다. ㅎㅎㅎㅎㅎ 근데 좀 재미졌음...

그리고 어디에선가는 img src속성에 로컬파일경로를 넣어주면 된다고 하는데 참조하다가 테스트 좀 해보니 값 변경 후 이미지를 다시 로드시켜야 할 것 같아서 뒤지다가 다음과 같은 팁이 있었음.

d = new Date();
$("#myimg").attr("src", "/myimg.jpg?"+d.getTime());

하지만 소스가 없거나.. 결국 IE 에게 물읍을 꿇었...

  • 최종적으로 스톱하기 전 최종 소스
<div>
    <input type="file" name="image" onchange="loadname(this,'previewimg')"/>
    <img src="about:blank" name="previewimg" id="previewimg" alt="">
</div>
<br>
<div id="text"></div>
<br>
<a class="pre_a" href="javascript:;" alt="" target="_blank">preview test</a>

<script type="text/javascript">
function loadname(img, review_img) {

    var is_ie = (navigator.appName=="Microsoft Internet Explorer"),
        path = img.value,
        ext = path.substring(path.lastIndexOf('.') + 1).toLowerCase();  

    var txt = '<div>' + 'is_ie - ' + is_ie + '</div>'+
        '<div>' + 'path - ' + path + '</div>'+
        '<div>' + 'ext - ' + ext + '</div>';
    $('#text').html(txt);

    if (ext == "gif" || ext == "jpeg" || ext == "jpg" ||  ext == "png") {
        if (is_ie) {
            img.select();
            var img_path = document.selection.createRangeCollection()[0].text.toString() + '?' + (new Date().getTime().toString());
            $('#'+ review_img).attr('src', img_path);
            $('a.pre_a').attr('href', img_path);

        } else {
            if (img.files[0]) {
                var reader = new FileReader();  
                reader.onload = function (e) {  
                    $('#'+ review_img).attr('src', e.target.result);  
                }
                reader.readAsDataURL(img.files[0]);  
            }
        }
    }
} 
</script>

참고로 크롬, 파폭, IE10 이상 에서는 성공했다. 다만, IE9 이하 버전이.. 



좀 더 다듬은 소스(Edge 버전은 테스트 못했음).  

암튼, 하단 소스는 크롬, 파폭, IE 10 이상에서 테스트 성공한 케이스다. IE 9 이하 버전에서만 서버에 업로드를 하고 리턴 받아서 업로드 된 파일경로를 이미지태그 속성 src에 입력한다.

<div> <form id="submit_form"> <input type="file" name="uploadFile" accept="image/*" /><br> <img src="" id="preview_img" title="preview_img" style="max-height: 320px;"> </form> </div> <script> $(document).ready(function(){ $('input[name=uploadFile]').change(function(){ $('#preview_img').attr('src', loadPreview(this, 'preview_img')); }); }); function loadPreviewFileUpload(preview_img) { $("#submit_form").ajaxSubmit({ url: '/***/**Ajax.do', type: "post", data: $("#submit_form").serialize(), dataType : 'json', async : false, cache : false, success: function(data){ if (data.message != ""){ alert(data.message); return; } if (data.result == 1 && data.filename != ""){ var upload_path = IMG_URL + data.filename; $('#'+ preview_img).attr('src', upload_path); } } }); } function loadPreview(el_img, preview_img) { var is_ie = (navigator.appName=="Microsoft Internet Explorer"), path = el_img.value, real_path = "", ext = path.substring(path.lastIndexOf('.') + 1).toLowerCase(); if (!/(jpg|png|gif|jpeg)$/i.test(ext)) { alert('이미지파일 형식은 jpg, png, gif 만 등록 가능합니다.'); return; } if (is_ie) { var ver = get_ver_IE(); if (ver <= 9) { console.log('파일업로드를 실행합니다.'); loadPreviewFileUpload(preview_img);
} if (ver === 10) { loadPreviewFile(el_img.files[0], preview_img); } if (ver >= 11) { el_img.select(); real_path = document.selection.createRangeCollection()[0].text.toString() + '?' + (new Date().getTime().toString()); $('#'+ preview_img).attr('src', real_path); } } else { loadPreviewFile(el_img.files[0], preview_img); } } function loadPreviewFile(file, preview_img) { if (file) { var reader = new FileReader(); reader.onload = function(e) { $('#'+ preview_img).attr('src', e.target.result); } reader.readAsDataURL(file); } } function get_ver_IE() { var word, version = "N/A", agent = navigator.userAgent.toLowerCase(); /*IE old version ( IE 10 or Lower ) */ if ( navigator.appName == "Microsoft Internet Explorer" ) word = "msie "; else { /*IE 11 */ if ( agent.search("trident") > -1 ) word = "trident/.*rv:"; /*Edge */ else if ( agent.search("edge/") > -1 ) word = "edge/"; } var reg = new RegExp( word + "([0-9]{1,})(\\.{0,}[0-9]{0,1})" ); if ( reg.exec( agent ) != null ) version = RegExp.$1 + RegExp.$2; return parseInt(version, 10); } </script>


check ie version in javascript

반응형