파일업로드 이미지 미리보기 삽질
본문은 그냥 삽질한 내용의 기록이며 브라우저에서 미리보기 해결방안을 찾는 분이라면 피해가시길
음... 그냥 뻘짓을 좀 했다. 파일업로드는 아니고 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>