Cách Nhận Và Xử Lý File Excel Trong Form Html: Hướng Dẫn Chi Tiết Từ A‑z

Mục lục bài viế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:

  1. Cấu trúc cơ bản của thẻ <input type="file"> trong HTML
  2. Thuộc tính accept – cách giới hạn loại file được tải lên
  3. Kiểm tra và hiển thị tên file trên giao diện người dùng
  4. Xử lý file Excel trên server:
  5. PHP
  6. Node.js (Express + Multer)
  7. Python (Flask & Django)
  8. Java (Spring Boot)
  9. Đọc dữ liệu Excel bằng các thư viện phổ biến
  10. Bảo mật: Kiểm tra MIME type, kích thước, và nội dung
  11. Lưu trữ file: Local, Cloud (AWS S3, Google Cloud Storage), Database
  12. Ví dụ thực tế: Xây dựng một form nhận báo cáo tài chính
  13. 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.

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.

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ạngMIME typeExtension
Excel 97‑2003application/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 accept và 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:

  1. Kiểm tra MIME type và extension (đảm bảo không phải file độc hại).
  2. Kiểm tra kích thước (giới hạn tối đa, ví dụ 5 MB).
  3. Lưu trữ tạm thời.
  4. Đọc nội dung (nếu cần trích xuất dữ liệu).
  5. 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ả .xls và .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_excel tự động phát hiện định dạng .xls hoặc .xlsx nếu có xlrd (cho .xls) và openpyxl (cho .xlsx).
  • Đối với .xls mới, cần cài xlrd==1.2.0 vì 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
PHPPhpSpreadsheet.xls, .xlsx, .csvĐọc/ghi, định dạng màu, công thức
Node.jsExcelJS.xlsx (có plugin cho .xls)Hỗ trợ streaming, tạo file nhanh
Pythonpandas, openpyxl, xlrd.xlsx, .xlsPhân tích dữ liệu mạnh, tích hợp NumPy
JavaApache POI.xls, .xlsxĐọc/ghi, tạo biểu đồ, tương thích Android
.NET (C#)EPPlus, NPOI.xlsx, .xlsHiệ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

  1. Kiểm tra MIME type và extension – không dựa chỉ vào một trong hai.
  2. Giới hạn kích thước – tránh tấn công DoS.
  3. Quét virus – tích hợp ClamAV hoặc dịch vụ bảo mật.
  4. Lưu trữ tạm thời ở thư mục không công khai – tránh truy cập trái phép.
  5. Sử dụng tên file ngẫu nhiên – tránh overwrite và directory traversal.
  6. Xác thực người dùng – nếu chỉ một nhóm người mới có quyền upload.
  7. 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

Accept Excel File In Html
Accept Excel File In Html

7.1. Lưu trên server (Local)

  • Thư mục uploads/ với quyền 0755.
  • Đặ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 S3aws-sdk (Node), boto3 (Python), aws-sdk-phpĐộ bền 99.999999999%, CDN tích hợp
Google Cloud Storage@google-cloud/storageTích hợp IAM, chi phí thấp cho lưu trữ lâu dài
Azure Blob Storage@azure/storage-blobTí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:

  1. Xác định đúng MIME và extension trong HTML để hướng người dùng.
  2. Kiểm tra kỹ lưỡng ở phía server (type, size, nội dung) để ngăn chặn tấn công.
  3. 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ẽ.
  4. Bảo mật: quét virus, lưu trữ an toàn, giới hạn kích thước.
  5. Lưu trữ linh hoạt: local, cloud (S3, GCS), hoặc database.
  6. 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!

⚠️
LƯU Ý QUAN TRỌNG: Miễn trừ trách nhiệm: Mặc dù chúng tôi luôn nỗ lực để đảm bảo tính chính xác và cập nhật của thông tin, nhưng các quy định về giáo dục và tuyển sinh có thể thay đổi theo thời gian. BigSchool không chịu trách nhiệm về bất kỳ sai sót nào hoặc kết quả phát sinh từ việc sử dụng thông tin trên trang này. Độc giả nên liên hệ trực tiếp với nhà trường hoặc cơ quan chức năng để có thông tin mới nhất. Ngoài ra, BigSchool tuyệt đối không bán sản phẩm, khóa học hay cung cấp dịch vụ được nhắc đến trong bài.

Viết một bình luận