首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

HTML5 File API 客戶端文件上傳驗證:類型、大小、屬性即時校驗完整實現

     編輯:PHP 相關知識

HTML5 File API 實現客戶端文件上傳預校驗:類型、大小、多文件即時攔截

傳統文件上傳僅靠服務端校驗,用戶體驗差、浪費帶寬。HTML5 File API 賦予瀏覽器讀取本地文件元數據能力,可在選擇文件瞬間完成類型、大小、數量校驗,並即時反饋。本文提供基於 jQuery 的完整實現,含 MIME 映射、多文件處理、錯誤提示、進度預覽。

一、 核心 API:FileList 與 File 對象

<input type="file"> 的 change 事件中,event.target.files 返回 FileList,類數組,每項為 File 對象:

屬性類型說明
namestring文件名(含擴展名)
sizenumber文件大小(字節)
typestringMIME 類型(如 image/png),若無法識別為空串
lastModifiednumber最後修改時間戳(毫秒)
lastModifiedDateDate已棄用,改用 lastModified

二、 HTML 結構與數據屬性配置

<input type="file"
       id="uploader"
       multiple
       data-file_type="zip|png|jpg|pdf"
       data-max_size="5242880"
       data-max_count="5">
<div id="file-preview"></div>
  • data-file_type:允許的擴展名,| 分隔
  • data-max_size:單文件最大字節數(示例 5MB)
  • data-max_count:最大文件數(可選)

三、 MIME 類型映射表

const MIME_MAP = {
    // 圖片
    'jpg':  ['image/jpeg', 'image/pjpeg'],
    'jpeg': ['image/jpeg', 'image/pjpeg'],
    'png':  ['image/png', 'image/x-png'],
    'gif':  ['image/gif'],
    'webp': ['image/webp'],
    'bmp':  ['image/bmp'],
    // 文檔
    'pdf':  ['application/pdf'],
    'doc':  ['application/msword'],
    'docx': ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
    'xls':  ['application/vnd.ms-excel'],
    'xlsx': ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],
    'ppt':  ['application/vnd.ms-powerpoint'],
    'pptx': ['application/vnd.openxmlformats-officedocument.presentationml.presentation'],
    'txt':  ['text/plain'],
    // 壓縮
    'zip':  ['application/zip', 'application/x-zip-compressed'],
    'rar':  ['application/x-rar-compressed'],
    '7z':   ['application/x-7z-compressed'],
    // 視頻/音頻
    'mp4':  ['video/mp4'],
    'mp3':  ['audio/mpeg'],
    'wav':  ['audio/wav'],
};

四、 完整 jQuery 校驗邏輯


$('#uploader').on('change', function (e) {
    const $input = $(this);
    const files = e.target.files; // FileList
    const maxSize = parseInt($input.data('max_size'), 10);
    const maxCount = parseInt($input.data('max_count'), 10) || Infinity;
    const allowedExts = ($input.data('file_type') || '').split('|').filter(Boolean);
    const allowedMimes = getAllowedMimes(allowedExts);

    const $preview = $('#file-preview').empty();
    let validCount = 0;

    if (files.length > maxCount) {
        alert(`最多只能選擇 ${maxCount} 個文件`);
        $input.val('');
        return;
    }

    for (let i = 0; i < files.length; i++) {
        const file = files[i];
        let error = null;

        // 1. 類型校驗
        if (allowedMimes.length && !allowedMimes.includes(file.type)) {
            error = `文件類型 "${file.type || '未知'}" 不被允許`;
        }
        // 2. 大小校驗
        else if (file.size > maxSize) {
            error = `文件 "${file.name}" 超過限制 (${formatBytes(maxSize)})`;
        }

        if (error) {
            $preview.append(`<div class="text-danger">${escapeHtml(file.name)}: ${escapeHtml(error)}</div>`);
            continue;
        }

        // 3. 通過校驗,構建預覽
        validCount++;
        const previewHtml = `
            <div class="file-item d-flex align-items-center mb-2">
                <span class="me-2">${escapeHtml(file.name)}</span>
                <small class="text-muted me-2">(${file.type || '未知類型'}, ${formatBytes(file.size)})</small>
                <span class="badge bg-success">通過</span>
            </div>`;
        $preview.append(previewHtml);
    }

    // 可選:校驗失敗則清空 input,防止表單提交
    if (validCount !== files.length) {
        $input.val('');
    }
});

function getAllowedMimes(exts) {
    const mimes = [];
    exts.forEach(ext => {
        const list = MIME_MAP[ext.toLowerCase()];
        if (list) mimes.push(...list);
    });
    return [...new Set(mimes)]; // 去重
}

function formatBytes(bytes) {
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}

function escapeHtml(text) {
    const map = {'&': '&', '<': '<', '>': '>', '"': '"', "'": '''};
    return text.replace(/[&<>"']/g, m => map[m]);
}

五、 進階功能擴展

功能實現要點
圖片縮略圖預覽URL.createObjectURL(file) 生成 Blob URL,賦給 <img src>,上傳完成後 URL.revokeObjectURL() 釋放
分片/斷點續傳配合 File.prototype.slice() 切片,Web Worker 計算 SparkMD5,上傳前檢查服務端已有分片
拖拽上傳監聽 drop、dragover 事件,e.dataTransfer.files 獲取 FileList
上傳進度條XMLHttpRequest.upload.onprogress 或 fetch + ReadableStream
服務端二次校驗前端攔截不等於安全,服務端必須再次驗證 MIME(finfo_file)、大小、惡意內容掃描

六、 兼容性與降級策略

  • File API 支持:IE10+、Edge、Chrome、Firefox、Safari、Opera 全支持
  • IE9 及以下:無 files 屬性,需回退至 <iframe> 無刷新上傳或 Flash 上傳組件
  • 現代項目建議不再兼容 IE,直接要求現代瀏覽器

七、 結語

HTML5 File API 將文件校驗前置到客戶端,顯著提升用戶體驗並節省帶寬。核心邏輯只有三步:獲取 FileList → 遍歷 File 屬性 → 對比白名單。配合 MIME 映射表、友好提示、預覽功能,即可構建生產級上傳組件。切記:客戶端校驗只為體驗,服務端校驗才是安全底線。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved