Skip to content

上传校验

文件大小校验

核心属性:

  • file.size:文件的字节大小(单位:字节)。
js
const fileInput = document.getElementById('fileInput')

fileInput.addEventListener('change', (event) => {
  const file = event.target.files[0]
  if (!file) return

  const maxSize = 5 * 1024 * 1024 // 5MB
  if (file.size > maxSize) {
    alert('文件大小不能超过 5MB')
    fileInput.value = '' // 清空文件选择
    return
  }

  console.log('文件大小校验通过')
})

文件类型校验

方式一:通过 MIME 类型校验

核心属性:

  • file.type:文件的 MIME 类型,如 image/jpegimage/png 等。
js
const fileInput = document.getElementById('fileInput')

fileInput.addEventListener('change', (event) => {
  const file = event.target.files[0]
  if (!file) return

  const allowedTypes = ['image/jpeg', 'image/png', 'image/gif']
  if (!allowedTypes.includes(file.type)) {
    alert('只允许上传 JPG、PNG、GIF 格式的图片')
    fileInput.value = ''
    return
  }

  console.log('文件类型校验通过')
})

方式二:通过文件扩展名校验

核心属性:

  • file.name:文件名(包含扩展名),如 avatar.jpg
js
const fileInput = document.getElementById('fileInput')

fileInput.addEventListener('change', (event) => {
  const file = event.target.files[0]
  if (!file) return

  const fileName = file.name
  const allowedExtensions = ['jpg', 'jpeg', 'png', 'gif']
  const fileExtension = fileName.split('.').pop().toLowerCase()

  if (!allowedExtensions.includes(fileExtension)) {
    alert('只允许上传 JPG、PNG、GIF 格式的图片')
    fileInput.value = ''
    return
  }

  console.log('文件扩展名校验通过')
})

方式三:通过文件头(魔数)校验

更安全的方式,防止用户修改文件扩展名绕过校验。

核心方法:

  • file.slice(start, end):截取文件的部分内容,返回新的 Blob 对象。
  • blob.arrayBuffer():将 Blob 转换为 ArrayBuffer。
  • Uint8Array:用于读取二进制数据。
js
const fileInput = document.getElementById('fileInput')

// 常见文件类型的魔数(文件头)
const fileSignatures = {
  'image/jpeg': [0xff, 0xd8, 0xff],
  'image/png': [0x89, 0x50, 0x4e, 0x47],
  'image/gif': [0x47, 0x49, 0x46],
}

async function checkFileSignature(file, allowedTypes) {
  const arrayBuffer = await file.slice(0, 8).arrayBuffer()
  const uint8Array = new Uint8Array(arrayBuffer)

  for (const [type, signature] of Object.entries(fileSignatures)) {
    if (!allowedTypes.includes(type)) continue

    const match = signature.every((byte, index) => uint8Array[index] === byte)
    if (match) return type
  }

  return null
}

fileInput.addEventListener('change', async (event) => {
  const file = event.target.files[0]
  if (!file) return

  const allowedTypes = ['image/jpeg', 'image/png', 'image/gif']
  const actualType = await checkFileSignature(file, allowedTypes)

  if (!actualType) {
    alert('文件格式不正确或不支持')
    fileInput.value = ''
    return
  }

  console.log('文件头校验通过,实际类型:', actualType)
})

图片比例校验

核心对象和属性:

  • Image 对象:用于加载和获取图片信息。
  • img.width:图片的宽度(单位:像素)。
  • img.height:图片的高度(单位:像素)。
  • URL.createObjectURL(file):创建文件的临时 URL。
  • URL.revokeObjectURL(url):释放临时 URL,防止内存泄漏。
js
const fileInput = document.getElementById('fileInput')

fileInput.addEventListener('change', (event) => {
  const file = event.target.files[0]
  if (!file) return

  // 校验是否为图片
  if (!file.type.startsWith('image/')) {
    alert('请上传图片文件')
    fileInput.value = ''
    return
  }

  const img = new Image()
  const url = URL.createObjectURL(file)

  img.onload = () => {
    const width = img.width
    const height = img.height
    const ratio = width / height

    // 示例:校验比例为 16:9(允许误差 0.1)
    const targetRatio = 16 / 9
    const tolerance = 0.1

    if (Math.abs(ratio - targetRatio) > tolerance) {
      alert(`图片比例应为 16:9,当前比例为 ${ratio.toFixed(2)}`)
      fileInput.value = ''
      URL.revokeObjectURL(url)
      return
    }

    console.log('图片比例校验通过')
    URL.revokeObjectURL(url)
  }

  img.onerror = () => {
    alert('图片加载失败')
    fileInput.value = ''
    URL.revokeObjectURL(url)
  }

  img.src = url
})

图片尺寸校验

核心对象和属性:

  • Image 对象:用于加载和获取图片信息。
  • img.width:图片的宽度(单位:像素)。
  • img.height:图片的高度(单位:像素)。
js
const fileInput = document.getElementById('fileInput')

fileInput.addEventListener('change', (event) => {
  const file = event.target.files[0]
  if (!file) return

  if (!file.type.startsWith('image/')) {
    alert('请上传图片文件')
    fileInput.value = ''
    return
  }

  const img = new Image()
  const url = URL.createObjectURL(file)

  img.onload = () => {
    const width = img.width
    const height = img.height

    // 限制最小尺寸
    const minWidth = 800
    const minHeight = 600
    if (width < minWidth || height < minHeight) {
      alert(`图片尺寸不能小于 ${minWidth}x${minHeight}px`)
      fileInput.value = ''
      URL.revokeObjectURL(url)
      return
    }

    // 限制最大尺寸
    const maxWidth = 4096
    const maxHeight = 4096
    if (width > maxWidth || height > maxHeight) {
      alert(`图片尺寸不能大于 ${maxWidth}x${maxHeight}px`)
      fileInput.value = ''
      URL.revokeObjectURL(url)
      return
    }

    console.log('图片尺寸校验通过')
    URL.revokeObjectURL(url)
  }

  img.onerror = () => {
    alert('图片加载失败')
    fileInput.value = ''
    URL.revokeObjectURL(url)
  }

  img.src = url
})

基于 MIT 许可发布