+14

Vanilla JS: Xem preview khi upload ảnh

1. Yêu cầu

Yêu cầu bài toán là khi người dùng chọn ảnh từ máy tính thì chúng ta sẽ hiển thị hình ảnh preview để xem trước mà không cần phải upload lên server. Đây là một trong những bài tập vanilla Javascript ở mức cơ bản giúp các bạn làm quen, chủ yếu giải thích về Javascript nên phần giao diện sẽ không phân tích nhiều. Hi vọng với bài tập này các bạn sẽ thấy thích thú khi học Javascript.

2. HTML - CSS

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vanilla JS: Preview image file upload</title>
  <!-- bootstrap css 4.5.0 -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" />
  <style>
    .preview-img {max-width: 150px;margin: 0 1em 1em 0;padding: 0.5em;border: 1px solid #ccc; border-radius: 3px;}
  </style>
</head>
<body>
  <div class="container">
    <h1 class="my-5 text-center">Preview image file upload</h1>
    <input type="file" class="form-control mb-4" />
    <div class="preview"></div>
  </div>
<script> // code javascript </script>
</body>
</html>

3. Hướng giải quyết chính

  • Lắng nghe sự thay đổi (change) của input file
  • Lấy ra các file vừa chọn thông qua FileList
  • Kiểm tra đúng định dạng là ảnh
  • Sử dụng FileReader để đọc file
  • Hiển thị preview image

4. Javascript

Step 1: Lắng nghe sự thay đổi của input file

const ipnFileElement = document.querySelector('input')

ipnFileElement.addEventListener('change', function(e) {
  // code here
})

Step 2: Lấy ra file vừa được chọn

ipnFileElement.addEventListener('change', function(e) {
  // step 2
  const files = e.target.files
  console.log(111, files)
  console.log(222, files[0])
})

Ta thu được kết quả log như sau

Nếu muốn chọn được nhiều file thì html ta thêm multiple

<input type="file" multiple />

Ta thu được kết quả log khi chọn 3 file như sau

Trong đối tượng File ta có thể lấy các thông tin cơ bản của file như:

  • name: tên file
  • size: kích thước file (có thể dùng để giới hạn kích thước).
  • type: định dạng file (có thể dùng để validate có đúng là ảnh hay không).

Step 3: Kiểm tra phải là định dạng ảnh, nếu không đúng thì thông báo lỗi

const validImageTypes = ['image/gif', 'image/jpeg', 'image/png']

ipnFileElement.addEventListener('change', function(e) {
  const files = e.target.files
  const file = files[0]
  const fileType = file['type']
  
  if (!validImageTypes.includes(fileType)) {
    resultElement.insertAdjacentHTML(
      'beforeend',
      '<span class="preview-img">Chọn ảnh đi :3</span>'
    )
    return
  }
})

Step 4: Nếu đúng định dạng là ảnh thì tiếp tục sử dụng FileReader để đọc file ảnh được chọn ở trên

ipnFileElement.addEventListener('change', function(e) {
  const files = e.target.files
  const file = files[0]
  ...
  
  const fileReader = new FileReader()
  fileReader.readAsDataURL(file)
})

Step 5: Sử dụng FileReader onload để xử lý khi quá trình đọc file hoàn thành, chèn ảnh vào khu vực hiển thị

ipnFileElement.addEventListener('change', function(e) {
  ...
  const fileReader = new FileReader()
  fileReader.readAsDataURL(file)
  
  fileReader.onload = function() {
    const url = fileReader.result
    // Something like: data:image/png;base64,iVBORw...Ym57Ad6m6uHj96js
    const htmlString = `<img src="${url}" alt="${file.name}" class="img-thumbnail preview-img" />`
    resultElement.insertAdjacentHTML('beforeend', htmlString)
  }
})

Dưới đây là toàn bộ code JS

const ipnFileElement = document.querySelector('input')
const resultElement = document.querySelector('.preview')
const validImageTypes = ['image/gif', 'image/jpeg', 'image/png']

ipnFileElement.addEventListener('change', function(e) {
  const files = e.target.files
  const file = files[0]
  const fileType = file['type']

  if (!validImageTypes.includes(fileType)) {
    resultElement.insertAdjacentHTML(
      'beforeend',
      '<span class="preview-img">Chọn ảnh đi :3</span>'
    )
    return
  }

  const fileReader = new FileReader()
  fileReader.readAsDataURL(file)

  fileReader.onload = function() {
    const url = fileReader.result
    resultElement.insertAdjacentHTML(
      'beforeend',
      `<img src="${url}" alt="${file.name}" class="preview-img" />`
    )
  }
})

5. Kết quả


Bài viết đến đây là hết, hi vọng với bài viết này các bạn đã thêm được nhiều kiến thức bổ ích. Hẹn gặp lại các bạn ở bài viết tiếp theo!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí