일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- mysqlclient
- Object.freeze()
- liunx
- code-server
- Recoil
- 자바스크립트
- CloudFront
- 롤
- ci/cd
- 리액트
- riotapi
- e.preventDefault()
- docker
- Django
- e.stopPropagation()
- requests
- route53
- Github Actions
- AWS
- Python
- 카카오 로그인
- GlobalStyle
- ACM
- React
- s3
- 전역스타일
- typeorm
- 배포
- nestjs
- styled-component
- Today
- Total
군붕이의 메모장
자바스크립트로 Image Upload 및 Preview 구현하기 본문
중고나라 클론 프로젝트를 하면서 처음 해보는 이미지 업로드 기능에 부딪혔다.
여기저기 정보를 찾아보면서 공부한 내용을 정리해보려고 한다.
그리고 단순 input에 받는것이 아닌 다른 요소(div 등..)를 눌렀을 때 이미지 업로드와 동시에 preview 화면도 구현한다.
해당 포스트에 있는 코드는 이해를 돕기위해 코드를 모두 html 파일 내부에 작성했다.
실제 프로젝트에서는 html, css, js를 모두 나눠서 작업했다.
● HTML 에서 이미지를 업로드 받는방법
<input type="file" class="real-upload" accept="image/*" required multiple>
input type속성을 file로 정의하면 파일 업로드가 가능해진다.
또한 accept 속성을 img/*으로 지정할 경우 이미지 파일만 업로드가 가능해진다.
● 다른 요소(div 등..) 클릭시 input 이벤트가 발생하게 하는방법
내가 구현하고자 하는것은 div 를 눌렀을 때 input 의 파일선택창이 뜨는것이다.
이를 위해 input 은 display: none; 속성으로 숨기고 div에 대해서 input을 클릭하는 이벤트를 추가했다.
<body>
<input type="file" class="real-upload" accept="image/*" required multiple style="display: none;">
<div class="upload"></div>
<script>
const realUpload = document.querySelector('.real-upload');
const upload = document.querySelector('.upload');
upload.addEventListener('click', () => realUpload.click());
</script>
</body>
위 사진처럼 input 태그의 "파일 선택" 버튼을 누르지 않아도 잘 출력된다.
● input 태그에서 업로드한 파일을 다루는 방법
input 에 파일이 업로드되면 change event 가 발생하게 된다.
DOM.addEventListener 를 통해서 change event 를 지정하고 getImageFiles 함수를 등록했다.
<head>
<meta charset="UTF-8">
<style>
.real-upload {
display: none;
}
.upload {
width: 200px;
height: 200px;
background-color: antiquewhite;
}
</style>
</head>
<body>
<input type="file" class="real-upload" accept="image/*" required multiple>
<div class="upload"></div>
<script>
function getImageFiles(e) {
const files = e.currentTarget.files;
console.log(typeof files, files);
}
const realUpload = document.querySelector('.real-upload');
const upload = document.querySelector('.upload');
upload.addEventListener('click', () => realUpload.click());
realUpload.addEventListener('change', getImageFiles);
</script>
</body>
object 형식의 FileList 가 생성되었으며 출력시 위 처럼 출력된다.
● input 태그에서 업로드된 파일의 유효성검사 방법
우선 업로드된 이미지 파일의 갯수를 체크하는 방법이다.
유사배열인 FileList 를 ES6 Spread 문법을 통해 Array로 변환하여 length 메서드로 길이를 체크하는 방식이다.
function getImageFiles(e) {
const files = e.currentTarget.files;
if ([...files].length >= 7) {
alert('이미지는 최대 6개까지 업로드가 가능합니다.');
return;
}
}
다음은 업로드된 파일이 이미지 파일인지 체크하는 방법이다.
동일하게 유사배열인 FileList를 스프레드 문법을 통해 Array 로 변환해서 forEach 함수로 값을 체크한다.
function getImageFiles(e) {
const files = e.currentTarget.files;
[...files].forEach(file => {
if (!file.type.match("image/.*")) {
alert('이미지 파일만 업로드가 가능합니다.');
return;
}
})
}
!file.type.match("image/.*") 를 통해서 file 이 이미지인지 체크했다. 만약 이미지가 아닐경우 alert 를 띄우는 형식이다.
● 업로드된 이미지 파일 preview 표현하기
위에서 작성한 코드를 바탕으로 최종 코드를 완성했다. 로직은 아래와 같다
- div 를 눌렀을때 <input type="file"> 이 클릭되게 이벤트를 추가
- 업로드된 파일이 6개 이상인지 검사한다. 7개부터는 업로드가 불가능하다.
- 업로드된 파일이 모두 이미지 형식인지 검사한다.
- 이미지 파일을 li 태그내에 넣어서 ul 태그에 추가한다.
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
li {
list-style: none;
}
img {
width: 200px;
height: 200px;
}
.real-upload {
display: none;
}
.upload {
width: 200px;
height: 200px;
background-color: antiquewhite;
}
.image-preview {
width: 1300px;
height: 200px;
background-color: aquamarine;
display: flex;
gap: 20px;
}
</style>
</head>
<body>
<input type="file" class="real-upload" accept="image/*" required multiple>
<div class="upload"></div>
<ul class="image-preview"></ul>
<script>
function getImageFiles(e) {
const uploadFiles = [];
const files = e.currentTarget.files;
const imagePreview = document.querySelector('.image-preview');
const docFrag = new DocumentFragment();
if ([...files].length >= 7) {
alert('이미지는 최대 6개 까지 업로드가 가능합니다.');
return;
}
// 파일 타입 검사
[...files].forEach(file => {
if (!file.type.match("image/.*")) {
alert('이미지 파일만 업로드가 가능합니다.');
return
}
// 파일 갯수 검사
if ([...files].length < 7) {
uploadFiles.push(file);
const reader = new FileReader();
reader.onload = (e) => {
const preview = createElement(e, file);
imagePreview.appendChild(preview);
};
reader.readAsDataURL(file);
}
});
}
function createElement(e, file) {
const li = document.createElement('li');
const img = document.createElement('img');
img.setAttribute('src', e.target.result);
img.setAttribute('data-file', file.name);
li.appendChild(img);
return li;
}
const realUpload = document.querySelector('.real-upload');
const upload = document.querySelector('.upload');
upload.addEventListener('click', () => realUpload.click());
realUpload.addEventListener('change', getImageFiles);
</script>
</body>
위 코드를 기준으로 현재 진행중인 프로젝트에 적용했다. 이미지 업로드시 아래와 같이 표현된다.
'프로그래밍 언어 > 자바스크립트' 카테고리의 다른 글
자바스크립트 this 바인딩에 대한 이야기 (0) | 2023.05.19 |
---|---|
자바스크립트 변수와 호이스팅 (0) | 2023.05.18 |
event.preventDefault() 와 event.stopPropagation() (0) | 2021.07.08 |