Thực hành upload file bằng javascript có code mẫu

/ Lập trình web / Javascript
Thực hành upload file bằng javascript có code mẫu
1

Upload file là chức năng rất phổ biến trong các website hiện nay, ví dụ như upload file hình ảnh đại diện cho user, hay upload file hình ảnh cho sản phẩm, hay upload video/ nhạc cho các website đa phương tiện, upload file tài liệu cho website học thuật.

 

Chúng ta có thể sử dụng HTML và JAVASCRIPT để cho phép người dùng upload file từ máy tính/ điện thoại, kiểm tra file (validate), và tiến hành tải file lên server bằng AJAX.

 

Việc xử lý file upload bằng javascript sẽ mang đến nhiều lợi ích như:

- Tăng trải nghiệm người dùng.

- Giảm tải cho server.

Chi tiết các lợi ích này mình sẽ trình bày sau. Bây giờ chúng ta sẽ đi vào chi tiết cách tạo chức năng upload file bằng javascript. Bạn nào hóng code mẫu thì mình có để link tải mã nguồn tham khảo phía cuối bài viết.

 

Yêu cầu chức năng upload file

Trong phạm vi bài hướng dẫn này, mình sẽ trình bày chức năng upload file hình ảnh với các chức năng như sau:

- Hiển thị form upload hình ảnh gồm hình ảnh xem trước, nút "chọn hình", nút "gửi".

- Khi chọn file hình ảnh, tiến hành cập nhật hình xem trước, hiển thị các thông số của hình ảnh gồm: tên file, định dạng, dung lượng.

- Chỉ cho phép tải lên hình ảnh với định dạng PNG và JPG.

- Giới hạn dung lượng file ảnh là 30MB.

- Kiểm tra nội dung file có thật sự là hình ảnh hợp lệ hay không.

- Khi nhấn nút "gửi",  tiến hành gửi nội dung file hình tới địa chỉ URL được chỉ định thông qua AJAX và thông báo kết quả của việc upload file lên trình duyệt.

 

Các yêu cầu phía trên chỉ mang tính tham khảo, các bạn có thể tùy chỉnh để phù hợp với dự án.

 

Tiến hành thiết kế giao diện upload file hình ảnh bằng HTML và CSS

Tạo thư mục mới với các file như hình bên dưới.

 

Mở file index.html bằng trình soạn thảo code bất kỳ, nhập nội dung như sau:

 

<!DOCTYPE html>
<html>
    <head>
        <title>Upload file bằng javascript</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link href="css/index.css" rel="stylesheet" type="text/css"/>
    </head>
    <body>
        <main>
            <div class="container imageUploadContainer">
                <div>
                    <img 
                        src="img/default.jpg" 
                        alt="Ảnh xem trước" 
                        id="imagePreview">
                </div>
                <div class="imageUpload">
                    <input type="file" id="imageUploadInput" accept=".jpg,.png">
                    <span class="button" id="imageUploadInputBtn">Chọn Hình</span>
                    <span class="button" id="sendData">Gửi</span>
                </div>
                <div id="uploadFileStatus"></div>
                <div class="fileInfomation">
                    <p>
                        Tên file: 
                        <span id="fileInfomation_name">----</span>
                    </p>
                    <p>
                        Định dạng: 
                        <span id="fileInfomation_type">----</span>
                    </p>
                    <p>
                        Dung lượng: 
                        <span id="fileInfomation_size">----</span>
                    </p>
                </div>
            </div>
        </main>
        <script src="js/index.js" type="text/javascript"></script>
    </body>
</html>

 

Mở file index.css bằng trình soạn thảo code bất kỳ, nhập nội dung như sau:

*{
    padding: 0px;
    margin: 0px;
    font-family: sans-serif;
    box-sizing: border-box;
}
main{
    background-color: #dddddd;
    min-height: 300px;
    padding: 7.5px 15px;
}
.container{
    width: 100%;
    max-width: 1200px;
    margin-left: auto;
    margin-right: auto;
}
.imageUploadContainer{
    text-align: center;
}
.imageUpload{
    margin-top: 20px;
    padding: 7.5px 0;
}
.fileInfomation{
    margin-top: 20px;
}
#imageUploadInput{
    display: none;
}
#imagePreview{
    max-width: 100%;
    max-height: 700px;
}
#imageUploadInputBtn,
#sendData{
    display: inline-block;
    padding: 7.5px 15px;
    background-color: #0099cc;
    color: #ffffff;
    cursor: pointer;
    border-radius: 5px;
}

 

 

Mở file index.html trên trình duyệt, chúng ta sẽ thấy giao diện như hình:

 

 

 

Viết code javascript xử lý upload file

Theo như các yêu cầu đã đặt ra phía trên, chúng ta tiến hành viết code javascript cho file index.js như sau:

 

(function () {
    var imageUpload = function () {
        var self = this;
        this.selector = {
            fileInput: document.getElementById('imageUploadInput'),
            fileInputBtn: document.getElementById('imageUploadInputBtn'),
            imagePreview: document.getElementById('imagePreview'),
            status: document.getElementById('uploadFileStatus'),
            sendBtn: document.getElementById('sendData'),
            infoName: document.getElementById('fileInfomation_name'),
            infoType: document.getElementById('fileInfomation_type'),
            infoSize: document.getElementById('fileInfomation_size')
        };
        this.imageData = "";
        this.fileTypes = ['image/png', 'image/jpeg'];
        this.maxSize = 30 * 1024 * 1024; // 30MB
        this.uploadUrl = 'https://tutrithuc.com/TestAPI/imageUpload';
        this.onChangeInput = function (e) {
            // Reset file data / image preview
            self.selector.status.innerHTML = '';
            self.selector.imagePreview.setAttribute('src', "img/default.jpg");
            self.imageData='';
            
            // Get the current file upload
            var file = e.target.files[0];
            this.selector.infoName.innerHTML = file.name;
            this.selector.infoType.innerHTML = file.type;
            this.selector.infoSize.innerHTML = file.size + " bytes"; // in bytes

            // Validate file type
            if (this.fileTypes.indexOf(file.type) == -1) {
                self.selector.status.innerHTML = "File không hợp lệ (chỉ file hình jpg và hình png được chấp nhận)";
                return;
            }
            
            // Validate file size
            if (file.size > this.maxSize) {
                self.selector.status.innerHTML = "Dung lượng file vượt quá giới hạn (tối đa 30MB được chấp nhận)";
                return;
            }

            var reader = new FileReader();
            reader.onload = function (e) {
                self.imageData = e.target.result;
                
                // Validate file content
                self.selector.imagePreview.onerror = function(){
                    self.imageData = "";
                    self.selector.imagePreview.setAttribute('src', "img/default.jpg");
                    self.selector.status.innerHTML = 'Nội dung hình không hợp lệ';
                };
                self.selector.imagePreview.setAttribute('src', self.imageData);
            };
            reader.readAsDataURL(file);
        };
        this.sendData = function () {
            // Validate when file content is empty
            if (this.imageData == ""){
                self.selector.status.innerHTML = 'Vui lòng chọn hình để tải lên';
                return;
            }
            
            // Prevent double click
            var data = {
                'imageData': this.imageData
            };
            this.imageData = "";
            
            var request = new XMLHttpRequest();
            request.open("POST", this.uploadUrl);
            request.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
            request.onreadystatechange = function () {
                if (this.readyState === 4 && this.status === 200) {
                    self.selector.status.innerHTML = "Upload thành công";
                } else {
                    console.log(this.responseText);
                    self.selector.status.innerHTML = "Đã có lỗi xảy ra, không upload được hình";
                }
            };

            // Send request to server
            request.send(JSON.stringify(data));
        };

        /*
         * Event trigger
         */
        this.selector.fileInput.addEventListener('change', function (e) {
            self.onChangeInput(e);
        });
        this.selector.fileInputBtn.addEventListener('click', function () {
            self.selector.fileInput.click();
        });
        this.selector.sendBtn.addEventListener('click', function () {
            self.sendData();
        });
    };
    window.addEventListener("DOMContentLoaded", function () {
        console.log('DOM is loaded');
        new imageUpload();
    });
})();

 

Mình sẽ diễn giải cách sử dụng và cấu trúc file index.js ngay bên dưới.

 

Kiểm tra hoạt động của chức năng upload hình ảnh bằng javascript

Tải lại file index.html đang mở trên trình duyệt, bây giờ chúng ta đã có thể sử dụng chức năng upload hình ảnh theo đúng với các yêu cầu đã đặt ra.

 

Tình huống 1: Tải hình ảnh thành công.

  1. Nhấn vào nút "Chọn hình". 
  2. Tìm và chọn một tấm hình (.JPG) với dung lượng nhỏ hơn 30MB.
  3. Check hình ảnh xem trước và các thông số của hình vừa tải lên.

 

Và đây là hình ảnh kết quả mà mình đã thực hiện:

 

 

 

Tình huống 2: Định dạng file tải lên không phải là JPG / PNG

  1. Nhấn vào nút "Chọn hình". 
  2. Tìm và chọn một file với định dạng không hợp lệ
    • File ảnh với định dạng GIF.
    • File pdf.
    • File word.
    • File nhạc.
    • File HTML
    • ...
  3. Check hình ảnh xem trước(được đặt lại về hình mặc định) và các thông số của hình vừa tải lên.

 

Và đây là kết quả khi mình đã chọn tải lên một file HTML:

 

 

 

Tình huống 3: Nội dung file tải lên không phải là file ảnh hợp lệ

  1. Nhấn vào nút "Chọn hình". 
  2. Tìm và chọn một file không phải là hình ảnh hợp lệ (file ảnh SVG được đổi tên thành "abc.jpg")
  3. Check hình ảnh xem trước(được đặt lại về hình mặc định) và các thông số của hình vừa tải lên.

 

Và đây là kết quả khi mình đã chọn tải lên một file SVG nhưng đã được đổi tên thành "52498.jpg":

 

 

 

Các bạn có thể tự kiểm tra thêm các tình huống khác nhé.

 

Diễn giải cách hoạt động xử lý upload file bằng javascript

- Trước tiên, chúng ta dùng thẻ input với type="file" để cho phép người dùng có thể chọn duyệt file bằng máy tính hoặc điện thoại di động. Tuy nhiên, chúng ta sẽ ẩn thẻ input này đi và hiển thị một nút nhấn thay thế, chúng sẽ sẽ bắt sự kiện khi người dùng nhấn vào nút nhấn thì sẽ dùng javascript gọi sự kiện click cho thẻ input.

 

Trích dẫn file index.html:

 

<input type="file" id="imageUploadInput" accept=".jpg,.png">
<span class="button" id="imageUploadInputBtn">Chọn Hình</span>

 

Trích dẫn file index.css:

 

#imageUploadInput{
    display: none;
}

 

Trích dẫn file index.js

 

(function () {
    var imageUpload = function () {
        var self = this;
        this.selector = {
            fileInput: document.getElementById('imageUploadInput'),
            fileInputBtn: document.getElementById('imageUploadInputBtn')
        };

        /*
         * Event trigger
         */
        this.selector.fileInputBtn.addEventListener('click', function () {
            self.selector.fileInput.click();
        });
    };
    window.addEventListener("DOMContentLoaded", function () {
        console.log('DOM is loaded');
        new imageUpload();
    });
})();

 

 

Tiếp đến, chúng ta tiến hành bắt sự kiện change của thẻ file input, gọi hàm onChangeInput() để đọc và xử lý dữ liệu.

 

Trích dẫn file index.js:

 

(function () {
    var imageUpload = function () {
        var self = this;
        this.selector = {
            fileInput: document.getElementById('imageUploadInput'),
            fileInputBtn: document.getElementById('imageUploadInputBtn'),
            imagePreview: document.getElementById('imagePreview'),
            status: document.getElementById('uploadFileStatus'),
            sendBtn: document.getElementById('sendData'),
            infoName: document.getElementById('fileInfomation_name'),
            infoType: document.getElementById('fileInfomation_type'),
            infoSize: document.getElementById('fileInfomation_size')
        };
        this.imageData = "";
        this.fileTypes = ['image/png', 'image/jpeg'];
        this.maxSize = 30 * 1024 * 1024; // 30MB
        this.onChangeInput = function (e) {
            // Reset file data / image preview
            self.selector.status.innerHTML = '';
            self.selector.imagePreview.setAttribute('src', "img/default.jpg");
            self.imageData='';
            
            // Get the current file upload
            var file = e.target.files[0];
            this.selector.infoName.innerHTML = file.name;
            this.selector.infoType.innerHTML = file.type;
            this.selector.infoSize.innerHTML = file.size + " bytes"; // in bytes

            // Validate file type
            if (this.fileTypes.indexOf(file.type) == -1) {
                self.selector.status.innerHTML = "File không hợp lệ (chỉ file hình jpg và hình png được chấp nhận)";
                return;
            }
            
            // Validate file size
            if (file.size > this.maxSize) {
                self.selector.status.innerHTML = "Dung lượng file vượt quá giới hạn (tối đa 30MB được chấp nhận)";
                return;
            }

            var reader = new FileReader();
            reader.onload = function (e) {
                self.imageData = e.target.result;
                
                // Validate file content
                self.selector.imagePreview.onerror = function(){
                    self.imageData = "";
                    self.selector.imagePreview.setAttribute('src', "img/default.jpg");
                    self.selector.status.innerHTML = 'Nội dung hình không hợp lệ';
                };
                self.selector.imagePreview.setAttribute('src', self.imageData);
            };
            reader.readAsDataURL(file);
        };
        

        /*
         * Event trigger
         */
        this.selector.fileInput.addEventListener('change', function (e) {
            self.onChangeInput(e);
        });
    };
    window.addEventListener("DOMContentLoaded", function () {
        console.log('DOM is loaded');
        new imageUpload();
    });
})();

 

Mình có comment khá chi tiết trong hàm onChangeInput(). Có một số lưu ý sau:

- Sử dụng đối tượng FileReader có sẵn để đọc file bằng javascript.

- Trong bài hướng dẫn này, mình chỉ làm mẫu việc đọc một file, đọc nhiều file thì mình sẽ hướng dẫn trong những bài sau.

 

var file = e.target.files[0];

 

- file.size là để lấy ra dung lượng tính theo bytes của đối tượng file list item.

- Nội dung hình không hợp lệ nghĩa là một file với nội dung không hợp lệ với file type tương ứng. Điều này xảy ra khi người dùng tải lên một file không phải là ảnh jpeg nhưng lại đặt tên file là "abc.jpg", tương tự đối với ảnh PNG.

 

Sau khi đã đọc được nội dung file, chúng ta sử dụng hàm sendData() để gửi nội dung file tới server.

Trích dẫn file index.js:

 

this.sendData = function () {
	// Validate when file content is empty
	if (this.imageData == ""){
		self.selector.status.innerHTML = 'Vui lòng chọn hình để tải lên';
		return;
	}
	
	// Prevent double click
	var data = {
		'imageData': this.imageData
	};
	this.imageData = "";
	
	var request = new XMLHttpRequest();
	request.open("POST", this.uploadUrl);
	request.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
	request.onreadystatechange = function () {
		if (this.readyState === 4 && this.status === 200) {
			self.selector.status.innerHTML = "Upload thành công";
		} else {
			console.log(this.responseText);
			self.selector.status.innerHTML = "Đã có lỗi xảy ra, không upload được hình";
		}
	};

	// Send request to server
	request.send(JSON.stringify(data));
};

 

Trong hàm sendData(), chúng ta có một số lưu ý:

- Sử dụng AJAX gửi request tới server

var request = new XMLHttpRequest();

- Khi gửi request tới server, cần dùng javascript để tạo chuỗi JSON cho tham số truyền đi:

request.send(JSON.stringify(data));

 

Lợi ích khi xử lý file upload bằng javascript

- Tăng trải nghiệm người dùng. Chúng ta sẽ kiểm tra định dạng file, dung lượng file để có thể đưa ra các thông báo lỗi ngay khi đọc xong file, người dùng sẽ không phải chờ cho đến khi file được tải lên server rồi mới thấy lỗi xảy ra. Hãy hình dung, nếu người dùng tải lên một file video với dung lượng 4GB, quá trình tải lên server sẽ mất khoảng hơn 10 phút, sau khi chờ đợi, người dùng lại nhận được một thông báo rằng định dạng video không hợp lệ, thời gian của người dùng bị lãng phí một cách không đáng. Bên cạnh đó, chúng ta có thể hiển thị ngay file hình ảnh (hoặc video, nhạc) để người dùng xem trước, trước khi người dùng quyết định tải lên server, phần nào giúp người dùng yên tâm hơn rằng mình đã chọn đúng file cần upload.

 

- Giảm tải cho server. File upload vẫn phải được kiểm tra lại phía server một lần nữa để đảm bảo an toàn. Vậy, giảm tải cho server có phải là không có ? Thật ra, trong các trường hợp thông thường, lỗi đã được phát hiện phía máy người dùng trước khi tải lên server, nói cách khác, các file tải lên server là các file như mong muốn (không có lỗi). Trong các trường hợp không thông thường, như người dùng cố tình can thiệp vào javascript để vượt qua bước kiểm tra file upload, thì server mới đưa ra lỗi để đảm bảo an toàn.

 

Thảo luận về xử lý file upload bằng javascript

Trên tinh thần xây dựng cùng phát triển, các bạn có ý kiến hay góp ý về bài hướng dẫn, xin vui lòng để lại bình luận bên dưới nhé.

 

Code tham khảo chức năng upload file bằng javascript

Mã nguồn của bài hướng dẫn mình có tải lên Google Drive, bạn nào có nhu cầu có thể tải về tham khảo nhé.

https://drive.google.com/file/d/1Xq21ihB9hu04TgnfGaQZP-MfYHy5Rycp/view?usp=sharing

 

Tạo vào 04/03/2023, Cập nhật 1 năm trước

Bình luận

Hãy là nguời đầu tiên bình luận về Thực hành upload file bằng javascript có code mẫu

Bài viết có vấn đề ? Hãy cho chúng tôi biết.

Gửi báo cáo sai phạm
Bạn đang đọc bài viết Thực hành upload file bằng javascript có code mẫu

Hãy để nguồn Suta.media khi phát hành lại nội dung này !