Có thể bạn quan tâm: Khám Phá Ablebits Data Tab Trong Excel: Công Cụ Đắc Lực Giúp Tối Ưu Hóa Dữ Liệu Và Nâng Cao Năng Suất
Giới thiệu chung
Trong thời đại số hiện nay, việc thu thập dữ liệu từ người dùng qua các biểu mẫu (form) trên website là một nhu cầu phổ biến. Đặc biệt, nhiều doanh nghiệp, tổ chức giáo dục hay các dự án nghiên cứu thường yêu cầu người dùng tải lên các file Excel (định dạng .xls hoặc .xlsx) để nộp báo cáo, bảng tính chi phí, danh sách khách hàng, kết quả khảo sát, v.v.
Tuy nhiên, không phải ai cũng biết cách cấu hình một form HTML để chấp nhận (accept) file Excel, cũng như cách đọc, kiểm tra, và lưu trữ các file này một cách an toàn và hiệu quả. Bài viết dưới đây sẽ cung cấp cho bạn một hướng dẫn chi tiết, từ việc chuẩn bị giao diện người dùng (frontend) cho đến xử lý file trên server (backend) bằng các công nghệ phổ biến như PHP, Node.js, Python (Flask/Django), và thậm chí là JavaScript thuần (client‑side) nếu bạn muốn thực hiện một số kiểm tra nhanh.
Bài viết sẽ được chia thành các phần chính:
- Cấu trúc cơ bản của thẻ
<input type="file">trong HTML - Thuộc tính
accept– cách giới hạn loại file được tải lên - Kiểm tra và hiển thị tên file trên giao diện người dùng
- Xử lý file Excel trên server:
- PHP
- Node.js (Express + Multer)
- Python (Flask & Django)
- Java (Spring Boot)
- Đọc dữ liệu Excel bằng các thư viện phổ biến
- Bảo mật: Kiểm tra MIME type, kích thước, và nội dung
- Lưu trữ file: Local, Cloud (AWS S3, Google Cloud Storage), Database
- Ví dụ thực tế: Xây dựng một form nhận báo cáo tài chính
- FAQ – Những câu hỏi thường gặp
Sau khi đọc xong, bạn sẽ có thể tự tin tạo một form HTML chấp nhận file Excel, xử lý chúng một cách an toàn và tích hợp vào dự án của mình.
Có thể bạn quan tâm: 6 Lọ Tài Chính Excel: Bí Quyết Quản Lý Tài Chính Cá Nhân Và Doanh Nghiệp Hiệu Quả
1. Thẻ <input type="file"> – Nền tảng của việc tải lên file
1.1. Cú pháp cơ bản
<form action="/upload" method="post" enctype="multipart/form-data"> <label for="excelFile">Chọn file Excel:</label> <input type="file" id="excelFile" name="excelFile"> <button type="submit">Gửi</button>
</form>
enctype="multipart/form-data": Bắt buộc khi form chứa file, giúp trình duyệt mã hoá dữ liệu dưới dạng multipart.method="post": Thông thường dùng POST để truyền file vì GET không hỗ trợ body lớn.
1.2. Thuộc tính multiple
Nếu bạn muốn cho phép người dùng tải lên nhiều file Excel cùng lúc, chỉ cần thêm multiple:
<input type="file" id="excelFiles" name="excelFiles" multiple>
Lưu ý: Khi có multiple, tên trường (name) thường phải là một mảng (excelFiles) để server nhận đúng.
Có thể bạn quan tâm: 3 Axis Chart Trong Excel: Hướng Dẫn Chi Tiết Từ Cơ Bản Đến Nâng Cao
2. Thuộc tính accept – Giới hạn loại file được chọn
Thuộc tính accept trong thẻ <input type="file"> cho phép bạn hạn chế các loại file mà trình duyệt hiển thị trong hộp thoại chọn file. Đối với Excel, chúng ta thường dùng:
| Định dạng | MIME type | Extension |
|---|---|---|
| Excel 97‑2003 | application/vnd.ms-excel | .xls |
| Excel 2007+ (OpenXML) | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | .xlsx |
| CSV (đôi khi được dùng) | text/csv | .csv |
2.1. Cú pháp accept
<input type="file" name="excelFile" accept=".xls,.xlsx,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
Bạn có thể chỉ định extension (.xls,.xlsx) hoặc MIME type. Đối với tính tương thích tốt nhất, nên liệt kê cả hai.
2.2. Kiểm tra accept trên các trình duyệt
- Chrome, Edge, Firefox: Tôn trọng
acceptvà chỉ hiển thị các file phù hợp. - Safari (iOS): Đôi khi không hoàn toàn tuân thủ, do giới hạn hệ thống. Bạn cần kiểm tra lại phía server để chắc chắn.
3. Cải thiện trải nghiệm người dùng (UX) khi chọn file
3.1. Hiển thị tên file đã chọn
<input type="file" id="excelFile" name="excelFile" accept=".xls,.xlsx" onchange="showFileName(this)">
<span id="fileName"></span> <script>
function showFileName(input) { const fileNameSpan = document.getElementById('fileName'); if (input.files && input.files0) { fileNameSpan.textContent = input.files0.name; } else { fileNameSpan.textContent = ''; }
}
</script>
3.2. Thêm preview nhanh (chỉ tên, số sheet, kích thước)
Bạn có thể dùng FileReader (JavaScript) để đọc một phần nhỏ của file và hiển thị thông tin:
function previewExcel(file) { const reader = new FileReader(); reader.onload = function(e) { // Chỉ lấy 1-2KB đầu tiên để kiểm tra magic number const arr = (new Uint8Array(e.target.result)).subarray(0, 4); let header = ""; for(let i = 0; i < arr.length; i++) { header += arri.toString(16); } console.log("Header:", header); // Dùng để xác nhận định dạng }; reader.readAsArrayBuffer(file.slice(0, 4));
}
Mặc dù không thể đọc toàn bộ sheet trên client mà không dùng thư viện nặng, việc kiểm tra magic number giúp giảm rủi ro tải lên file giả.
4. Xử lý file Excel trên server
Sau khi người dùng gửi file, server sẽ nhận và cần:
- Kiểm tra MIME type và extension (đảm bảo không phải file độc hại).
- Kiểm tra kích thước (giới hạn tối đa, ví dụ 5 MB).
- Lưu trữ tạm thời.
- Đọc nội dung (nếu cần trích xuất dữ liệu).
- Lưu trữ cuối cùng (cơ sở dữ liệu, cloud, v.v.).
4.1. PHP – Sử dụng $_FILES và thư viện PhpSpreadsheet
4.1.1. Cấu hình PHP (php.ini)
upload_max_filesize = 10M
post_max_size = 12M
max_file_uploads = 20
4.1.2. Form HTML (đã có accept)
<form action="upload.php" method="post" enctype="multipart/form-data"> <input type="file" name="excelFile" accept=".xls,.xlsx" required> <button type="submit">Upload</button>
</form>
4.1.3. File upload.php
<?php
require 'vendor/autoload.php'; // Composer autoload for PhpSpreadsheet use PhpOffice\PhpSpreadsheet\IOFactory; // Đặt thư mục lưu tạm
$targetDir = __DIR__ . '/uploads/';
if (!is_dir($targetDir)) { mkdir($targetDir, 0755, true);
} // Kiểm tra lỗi upload
if (!isset($_FILES'excelFile') || $_FILES'excelFile''error' !== UPLOAD_ERR_OK) { die('Upload error.');
} // Kiểm tra MIME và extension
$allowedMime = 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
;
$allowedExt = 'xls', 'xlsx'; $finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($_FILES'excelFile''tmp_name');
$ext = strtolower(pathinfo($_FILES'excelFile''name', PATHINFO_EXTENSION)); if (!in_array($mime, $allowedMime) || !in_array($ext, $allowedExt)) { die('File type not allowed.');
} // Kiểm tra kích thước (max 5 MB)
$maxSize = 5 1024 1024;
if ($_FILES'excelFile''size' > $maxSize) { die('File too large.');
} // Di chuyển file tới thư mục tạm
$targetFile = $targetDir . uniqid('excel_') . '.' . $ext;
if (!move_uploaded_file($_FILES'excelFile''tmp_name', $targetFile)) { die('Failed to move uploaded file.');
} // Đọc dữ liệu Excel
try { $spreadsheet = IOFactory::load($targetFile); $sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, true); // Xử lý $sheetData tùy nhu cầu, ví dụ lưu vào DB echo '<pre>'; print_r($sheetData); echo '</pre>';
} catch (Exception $e) { die('Error reading Excel file: ' . $e->getMessage());
} // Xóa file tạm nếu không cần lưu lâu
unlink($targetFile);
?>
4.1.4. Thư viện PhpSpreadsheet
- Cài đặt:
composer require phpoffice/phpspreadsheet - Hỗ trợ cả
.xlsvà.xlsx. - Cho phép đọc, ghi, và chuyển đổi sang CSV, HTML, PDF.
4.2. Node.js – Express + Multer + ExcelJS
4.2.1. Cài đặt
npm init -y
npm install express multer exceljs
4.2.2. Server (app.js)
const express = require('express');
const multer = require('multer');
const ExcelJS = require('exceljs');
const path = require('path');
const fs = require('fs'); const app = express();
const upload = multer({ dest: 'uploads/', limits: { fileSize: 5 1024 1024 }, // 5 MB fileFilter: (req, file, cb) => { const allowed = 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ; if (allowed.includes(file.mimetype)) { cb(null, true); } else { cb(new Error('Invalid file type'), false); } }
}); app.post('/upload', upload.single('excelFile'), async (req, res) => { if (!req.file) return res.status(400).send('No file uploaded.'); const filePath = path.resolve(req.file.path); const workbook = new ExcelJS.Workbook(); try { await workbook.xlsx.readFile(filePath); // works for .xlsx // Nếu .xls, dùng workbook.xls.readFile (cần thêm thư viện khác) const worksheet = workbook.worksheets0; const rows = ; worksheet.eachRow({ includeEmpty: true }, (row, rowNumber) => { rows.push(row.values); }); // Ở đây bạn có thể lưu rows vào DB, trả về JSON, v.v. res.json({ rows }); } catch (err) { console.error(err); res.status(500).send('Error processing Excel file.'); } finally { // Xóa file tạm fs.unlinkSync(filePath); }
}); app.listen(3000, () => console.log('Server listening on http://localhost:3000'));
4.2.3. HTML Form (đặt trong public/index.html)
<form action="/upload" method="post" enctype="multipart/form-data"> <input type="file" name="excelFile" accept=".xls,.xlsx" required> <button type="submit">Upload</button>
</form>
4.3. Python – Flask + openpyxl / pandas
4.3.1. Cài đặt môi trường
python -m venv venv
source venv/bin/activate
pip install Flask openpyxl pandas
4.3.2. Ứng dụng Flask (app.py)
from flask import Flask, request, jsonify, render_template_string
import os
from werkzeug.utils import secure_filename
import pandas as pd app = Flask(__name__)
app.config'MAX_CONTENT_LENGTH' = 5 1024 1024 # 5 MB
UPLOAD_FOLDER = 'uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
ALLOWED_EXT = {'xls', 'xlsx'} def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)1.lower() in ALLOWED_EXT HTML_FORM = '''
<!doctype html>
<title>Upload Excel</title>
<h1>Upload Excel File</h1>
<form method=post enctype=multipart/form-data> <input type=file name=file accept=".xls,.xlsx" required> <input type=submit value=Upload>
</form>
''' @app.route('/', methods='GET', 'POST')
def upload_file(): if request.method == 'POST': if 'file' not in request.files: return 'No file part', 400 file = request.files'file' if file.filename == '': return 'No selected file', 400 if file and allowed_file(file.filename): filename = secure_filename(file.filename) path = os.path.join(UPLOAD_FOLDER, filename) file.save(path) # Đọc bằng pandas try: df = pd.read_excel(path) # Chuyển DataFrame thành JSON data = df.to_dict(orient='records') return jsonify(data) except Exception as e: return f'Error reading Excel: {e}', 500 finally: os.remove(path) else: return 'File type not allowed', 400 return render_template_string(HTML_FORM) if __name__ == '__main__': app.run(debug=True)
4.3.3. Lưu ý
pandas.read_exceltự động phát hiện định dạng.xlshoặc.xlsxnếu cóxlrd(cho.xls) vàopenpyxl(cho.xlsx).- Đối với
.xlsmới, cần càixlrd==1.2.0vì các phiên bản mới không hỗ trợ.xls.
4.4. Java – Spring Boot + Apache POI
4.4.1. Thêm dependency (pom.xml)
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.3</version> </dependency>
</dependencies>
4.4.2. Controller
@RestController
public class ExcelUploadController { private static final long MAX_SIZE = 5 1024 1024; // 5 MB private static final List<String> ALLOWED_TYPES = List.of( "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ); @PostMapping("/upload") public ResponseEntity<?> handleUpload(@RequestParam("excelFile") MultipartFile file) { if (file.isEmpty()) { return ResponseEntity.badRequest().body("No file selected"); } if (file.getSize() > MAX_SIZE) { return ResponseEntity.status(HttpStatus.PAYLOAD_TOO_LARGE) .body("File exceeds max size"); } String contentType = file.getContentType(); if (!ALLOWED_TYPES.contains(contentType)) { return ResponseEntity.badRequest().body("Invalid file type"); } try (InputStream is = file.getInputStream()) { Workbook workbook = WorkbookFactory.create(is); Sheet sheet = workbook.getSheetAt(0); List<List<String>> rows = new ArrayList<>(); for (Row row : sheet) { List<String> cells = new ArrayList<>(); for (Cell cell : row) { cells.add(cell.toString()); } rows.add(cells); } return ResponseEntity.ok(rows); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("Error processing Excel: " + e.getMessage()); } }
}
4.4.3. HTML Form (đặt trong src/main/resources/static/index.html)
<form action="/upload" method="post" enctype="multipart/form-data"> <input type="file" name="excelFile" accept=".xls,.xlsx" required> <button type="submit">Upload</button>
</form>
5. Đọc dữ liệu Excel – Các thư viện phổ biến
| Ngôn ngữ | Thư viện | Định dạng hỗ trợ | Điểm mạnh |
|---|---|---|---|
| PHP | PhpSpreadsheet | .xls, .xlsx, .csv | Đọc/ghi, định dạng màu, công thức |
| Node.js | ExcelJS | .xlsx (có plugin cho .xls) | Hỗ trợ streaming, tạo file nhanh |
| Python | pandas, openpyxl, xlrd | .xlsx, .xls | Phân tích dữ liệu mạnh, tích hợp NumPy |
| Java | Apache POI | .xls, .xlsx | Đọc/ghi, tạo biểu đồ, tương thích Android |
| .NET (C#) | EPPlus, NPOI | .xlsx, .xls | Hiệu năng cao, LINQ |
Lưu ý: Khi chỉ cần kiểm tra nhanh (ví dụ: chỉ lấy 5 dòng đầu), hãy dùng streaming (ExcelJS streaming, POI SXSSF) để giảm bộ nhớ.
6. Bảo mật khi nhận file Excel
- Kiểm tra MIME type và extension – không dựa chỉ vào một trong hai.
- Giới hạn kích thước – tránh tấn công DoS.
- Quét virus – tích hợp ClamAV hoặc dịch vụ bảo mật.
- Lưu trữ tạm thời ở thư mục không công khai – tránh truy cập trái phép.
- Sử dụng tên file ngẫu nhiên – tránh overwrite và directory traversal.
- Xác thực người dùng – nếu chỉ một nhóm người mới có quyền upload.
- CORS – nếu API được gọi từ front‑end khác miền, cấu hình CORS hợp lý.
7. Lưu trữ file Excel

Có thể bạn quan tâm: Ablebits Ultimate Suite For Excel: Giải Pháp Toàn Diện Tối Ưu Hóa Công Việc Xử Lý Dữ Liệu
7.1. Lưu trên server (Local)
- Thư mục
uploads/với quyền0755. - Đặt cron job để xóa file cũ (ví dụ > 7 ngày).
7.2. Lưu trên Cloud
| Dịch vụ | SDK | Ưu điểm |
|---|---|---|
| AWS S3 | aws-sdk (Node), boto3 (Python), aws-sdk-php | Độ bền 99.999999999%, CDN tích hợp |
| Google Cloud Storage | @google-cloud/storage | Tích hợp IAM, chi phí thấp cho lưu trữ lâu dài |
| Azure Blob Storage | @azure/storage-blob | Tích hợp với Azure Functions |
Ví dụ (Node.js + AWS S3)
const AWS = require('aws-sdk');
const s3 = new AWS.S3({ region: 'us-east-1' }); await s3.upload({ Bucket: 'my-excel-bucket', Key: `uploads/${Date.now()}_${req.file.originalname}`, Body: fs.createReadStream(req.file.path), ContentType: req.file.mimetype
}).promise();
7.3. Lưu trong Database
- BLOB trong MySQL/PostgreSQL: Dùng khi file nhỏ (<5 MB) và cần truy vấn cùng các metadata.
- Metadata: Tên, người tải, thời gian, đường dẫn S3.
CREATE TABLE excel_files ( id SERIAL PRIMARY KEY, filename VARCHAR(255), mimetype VARCHAR(50), size BIGINT, data BYTEA, -- PostgreSQL BLOB uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
8. Ví dụ thực tế: Form nhận báo cáo tài chính
8.1. Yêu cầu
- Người dùng tải lên file Excel chứa bảng cân đối kế toán (cột A: tài khoản, cột B: số tiền).
- Hệ thống sẽ:
- Kiểm tra định dạng và kích thước.
- Đọc dữ liệu, tính tổng tiền.
- Lưu file lên S3 và lưu kết quả tính toán vào DB.
- Trả về JSON:
{ "total": 1234567, "fileUrl": "https://..." }.
8.2. Giải pháp (Node.js + Express + Multer + ExcelJS + AWS S3)
// server.js (rút gọn)
const express = require('express');
const multer = require('multer');
const ExcelJS = require('exceljs');
const AWS = require('aws-sdk');
const path = require('path');
const fs = require('fs'); const app = express();
const upload = multer({ dest: 'tmp/', limits: { fileSize: 510241024 } }); const s3 = new AWS.S3({ region: 'ap-southeast-1' }); app.post('/financial-report', upload.single('report'), async (req, res) => { if (!req.file) return res.status(400).json({ error: 'No file' }); const wb = new ExcelJS.Workbook(); try { await wb.xlsx.readFile(req.file.path); const ws = wb.getWorksheet(1); let total = 0; ws.eachRow((row, rowNumber) => { const amount = parseFloat(row.getCell(2).value) || 0; total += amount; }); // Upload to S3 const s3Key = `reports/${Date.now()}_${req.file.originalname}`; const uploadResult = await s3.upload({ Bucket: 'my-financial-reports', Key: s3Key, Body: fs.createReadStream(req.file.path), ContentType: req.file.mimetype }).promise(); // Xóa file tạm fs.unlinkSync(req.file.path); // Trả về kết quả res.json({ total, fileUrl: uploadResult.Location }); } catch (e) { console.error(e); res.status(500).json({ error: 'Processing error' }); }
}); app.listen(3000, () => console.log('Running on http://localhost:3000'));
8.3. Frontend (HTML + fetch)
<form id="reportForm"> <input type="file" name="report" accept=".xls,.xlsx" required> <button type="submit">Submit</button>
</form>
<div id="result"></div> <script>
document.getElementById('reportForm').addEventListener('submit', async e => { e.preventDefault(); const formData = new FormData(e.target); const resp = await fetch('/financial-report', { method: 'POST', body: formData }); const data = await resp.json(); document.getElementById('result').innerHTML = `Total: ${data.total}<br><a href="${data.fileUrl}" target="_blank">View file</a>`;
});
</script>
9. FAQ – Những câu hỏi thường gặp
9.1. Có thể chặn hoàn toàn việc người dùng tải lên file không phải Excel không?
Có. Ngoài accept ở phía client, bạn phải kiểm tra MIME type, extension và nội dung thực tế trên server. Đừng tin hoàn toàn vào accept vì người dùng có thể bỏ qua bằng cách thay đổi tên file.
9.2. Làm sao để đọc file .xls trong Node.js?
ExcelJS không hỗ trợ .xls gốc. Bạn có thể dùng node-xls hoặc xlsx (thư viện sheetjs) để chuyển đổi sang JSON, hoặc chuyển đổi file sang .xlsx bằng công cụ bên ngoài (LibreOffice headless).
9.3. Có cách nào để preview dữ liệu Excel trên trình duyệt mà không tải lên server?
Có. Thư viện SheetJS (xlsx) chạy trên phía client, cho phép đọc file thông qua FileReader và hiển thị bảng HTML ngay trên trình duyệt. Tuy nhiên, đối với file lớn (>5 MB) nên tránh vì sẽ tốn bộ nhớ.
<input type="file" id="excelInput" accept=".xls,.xlsx">
<div id="preview"></div> <script src="https://cdn.jsdelivr.net/npm/xlsx/dist/xlsx.full.min.js"></script>
<script>
document.getElementById('excelInput').addEventListener('change', e => { const file = e.target.files0; const reader = new FileReader(); reader.onload = function(ev) { const data = new Uint8Array(ev.target.result); const wb = XLSX.read(data, {type:'array'}); const ws = wb.Sheetswb.SheetNames0; const html = XLSX.utils.sheet_to_html(ws); document.getElementById('preview').innerHTML = html; }; reader.readAsArrayBuffer(file);
});
</script>
9.4. Làm sao để cho phép người dùng kéo thả (drag‑and‑drop) file?
Sử dụng các sự kiện dragover, drop và DataTransfer. Ví dụ:
const dropZone = document.getElementById('dropZone');
dropZone.addEventListener('dragover', e => e.preventDefault());
dropZone.addEventListener('drop', e => { e.preventDefault(); const files = e.dataTransfer.files; // Gửi files bằng fetch/FormData như bình thường
});
9.5. Có nên lưu file Excel nguyên bản hay chỉ lưu dữ liệu?
- Lưu nguyên bản: Đảm bảo tính pháp lý, cho phép người dùng tải lại file gốc. Thích hợp cho báo cáo, hợp đồng.
- Chỉ lưu dữ liệu: Giảm chi phí lưu trữ, tăng tốc độ truy vấn. Thích hợp cho phân tích dữ liệu.
Bạn có thể lưu cả hai: file gốc trên S3, dữ liệu trích xuất vào DB.
9.6. Cách xử lý file Excel có macro (VBA) an toàn?
Macro có thể chứa mã độc. Khi nhận file, không thực thi macro. Nếu cần kiểm tra, sử dụng công cụ quét virus hoặc tách macro ra bằng oletools (Python) và loại bỏ.
9.7. Có cần hỗ trợ đa ngôn ngữ (i18n) cho thông báo lỗi?
Có. Khi triển khai trên môi trường quốc tế, nên trả về mã lỗi (error code) và message dựa trên ngôn ngữ người dùng (ví dụ: dùng i18next trên frontend, hoặc Laravel translation trên backend).
Kết luận
Việc chấp nhận (accept) file Excel trong HTML không chỉ là việc thêm một thẻ <input type="file"> với thuộc tính accept. Để triển khai một giải pháp hoàn chỉnh, bạn cần:
- Xác định đúng MIME và extension trong HTML để hướng người dùng.
- Kiểm tra kỹ lưỡng ở phía server (type, size, nội dung) để ngăn chặn tấn công.
- Lựa chọn công nghệ backend phù hợp (PHP, Node.js, Python, Java…) và thư viện đọc Excel mạnh mẽ.
- Bảo mật: quét virus, lưu trữ an toàn, giới hạn kích thước.
- Lưu trữ linh hoạt: local, cloud (S3, GCS), hoặc database.
- Cải thiện UX: hiển thị tên file, preview, drag‑and‑drop.
Bằng cách áp dụng các bước và ví dụ trong bài viết, bạn sẽ có thể xây dựng một form tải lên file Excel chuyên nghiệp, an toàn và dễ bảo trì cho bất kỳ dự án web nào. Chúc bạn thành công!

Tiến sĩ Lê Thống Nhất sinh năm 1955 tại Nghệ An, là nhà giáo, nhà báo và doanh nhân trong lĩnh vực giáo dục. Ông từng giảng dạy Toán học tại Trường THPT Chuyên Phan Bội Châu và đảm nhiệm nhiều vai trò trong ngành giáo dục, từ viết sách, biên soạn tài liệu đến sáng lập các dự án hỗ trợ học tập trực tuyến.
Ông là người sáng lập BigSchool – nền tảng giáo dục trực tuyến kết nối giáo viên và học sinh cả nước. Ngoài ra, ông còn nổi tiếng với vai trò tác giả, diễn giả truyền cảm hứng và khách mời trên nhiều chương trình truyền hình, trong đó có “Ai là triệu phú” trên truyền hình VTV.
Trong suốt sự nghiệp, Tiến sĩ Lê Thống Nhất đã nhận nhiều giải thưởng giáo dục và được biết đến như một người luôn đổi mới, ứng dụng công nghệ vào dạy và học, góp phần lan tỏa tri thức và niềm say mê học tập cho thế hệ trẻ.
