07/09/2018, 10:36

Upload file sử dụng JavaScript và Iframe

Trong bài viết này chúng ta sẽ tìm hiểu cách upload tập tin sử dụng JavaScript với sự hỗ trợ của Iframe. Bước 1: Tạo HTML Form Đầu tiên bạn tạo một tập tin upload.htmltrong đó có chứa 1 form HTML như sau: <form action="process_upload.php" method="post" enctype="multipart/form-data" ...

Trong bài viết này chúng ta sẽ tìm hiểu cách upload tập tin sử dụng JavaScript với sự hỗ trợ của Iframe.

Bước 1: Tạo HTML Form

Đầu tiên bạn tạo một tập tin upload.htmltrong đó có chứa 1 form HTML như sau:

<form action="process_upload.php" method="post" enctype="multipart/form-data" target="iframe_upload">
    <div>
        <label>Choose File:</label>
        <input name="file_upload" type="file">
    </div>
    <div><input type="submit" name="submitBtn" value="Upload"></div>
</form>

<iframe class="hidden" name="iframe_upload" src="about:blank" style="awidth:0; height:0;"></iframe>

Ở form trên bạn lưu ý các điểm sau:

  • Thuôc tính action="process_upload.php" quy định form upload này sẽ được xử lý bởi file process_upload.php, chúng ta sẽ tạo file này ở bước tiếp theo.
  • Thuộc tính target="iframe_upload" sẽ khiến trình duyệt không reload lại trang mà thay vào đó dữ liệu trả về từ server sẽ hiển thị trong một iframe có tên là ifame_upload. Iframe này được tạo ở phía dưới form.
  • Thuộc tính enctype="multipart/form-data" cho phép form có thể upload tập tin lên server.

Bước 2: Xử Lý File Upload

Trong cùng thư mục chứa tập tin upload.htmlở trên bạn tạo một tập tin process_upload.php với nội dung như sau:

<?php
$uploads = dirname(__FILE__) . DIRECTORY_SEPARATOR .'uploads' . DIRECTORY_SEPARATOR;

$target_path = $uploads . basename( $_FILES['file_upload']['name']);

move_uploaded_file($_FILES['file_upload']['tmp_name'], $target_path);
?>

Đoạn mã PHP trên sẽ thực hiện việc di chuyển tập tin được upload lên server vào thư mục uploads nằm trong thư mục chứa tập tin process_upload.php này. Bạn cần tạo thư mục uploads nằm cùng cấp với tập tin process_upload.php như sau:

.
├── process_upload.php
├── upload.html
└── uploads

Trong trường hợp bạn sử dụng hệ điều hành Linux thì hãy chắc chắn rằng web server có quyền viết lên thư mục này. Bạn có thể làm điều này bằng cách thiết lập quyền cho thư mục này là 777 như sau:

$ sudo chmod 777 uploads

Bây giờ nếu bạn mở trang upload.html và thử upload tập tin bạn sẽ thấy tập tin upload được tạo ra trong thư mục uploads đồng thời trình duyệt vẫn hiển thị nội dung trang upload.html mà không chuyển tiếp về process_upload.php.

Như vậy tới đây bạn đã hoàn tất các bước cần thiết để thực hiện việc upload tập tin sử dụng JavaScript và Iframe. Bạn có thể tuỳ chọn tham khảo hai bước tiếp theo để hiển thông báo về trạng thái của việc upload thành công hay gặp lỗi.

Bước 3 (Tuỳ Chọn): Hiển Thị Trạng Thái Upload

Bạn thêm một thẻ <div> chứa thông tin về trang thái upload ở trên <form> như sau:

<div id="result"></div>
<form action="process_upload.php" method="post" enctype="multipart/form-data" target="iframe_upload">
...
```html

Thẻ này ban đầu sẽ không chứa bất cứ nội dung nào. Sau khi việc upload hoàn tất, dựa vào kết quả trả về từ server chúng ta sẽ hiển thị thông tin tương ứng. Trong file `process_upload` chúng ta sẽ sử dụng một biến là `$status` để theo dõi trạng thái upload tập tin trên server:

```php
<?php
$uploads = dirname(__FILE__) . DIRECTORY_SEPARATOR .'uploads' . DIRECTORY_SEPARATOR;

$status = 0;

$target_path = $uploads . basename( $_FILES['file_upload']['name']);

if(move_uploaded_file($_FILES['file_upload']['tmp_name'], $target_path)) {
    $status = 1;
}
?>

Bây giờ câu hỏi đặt ra là làm sao sử dụng giá trị của biến $status này vì khi tạo form chúng ta sử dụng thuộc tính target="iframe_upload" nên dữ liệu trả về từ server sẽ được hiển thị ở Iframe thay vì ở parent document (là trang upload.html). Câu trả lời ở đây khá đơn giản. Do Iframe hoàn toàn có quyền gọi JavaScript ở parent document, do đó chúng ta có thể tạo một hàm JavaScript thực hiện việc hiển thị thông báo về trạng thái dựa trên giá trị của biến $status nhưng sẽ gọi hàm này từ trong Iframe.

Trong file upload.html tạo hàm stopUpload() như sau:

function stopUpload(status){
        var result = ';
        if (status == 1){
            document.getElementById('result').innerHTML =
                '<span style="color: green;">The file was uploaded successfully!</span>';
        } else {
            document.getElementById('result').innerHTML = 
                '<span style="color: red;">There was an error during file upload!</span>';
        }
        return true;   
}

Cuối cùng trong process_upload.php thêm đoạn JavaScript sau vào cuối file:

<script language="javascript" type="text/javascript">
   window.top.window.stopUpload("<?php echo $status; ?>");
</script>

Bây giờ bạn reload trang và thực hiện việc upload file bạn sẽ thấy một dòng thông báo về trạng thái upload hiển thị. Để kiểm tra khi upload gặp lỗi bạn chỉ cần xoá thư mục uploads hoặc đổi tên thư mục này.

Bước 4 (Tuỳ Chọn): Hiển Thị Thanh Progress Bar

Ở bước này chúng ta sẽ thực hiện việc hiển thị thanh progress bar khi quá trình upload đang diễn ra và ẩn thanh này khi upload hoàn tất. Trong file upload.html bạn tạo một thẻ <div> ở phía trên form với nội dung như sau:

<div id="upload_progress" style="display: none;"><img src="loader.gif"></div>

Trong thẻ <div> trên được gắn id="upload_progress" và bên trong có một thẻ <img>với thuộc tính src="load.gif" là một ảnh động được tôi cung cấp sẵn trong source code. Ảnh này dùng để hiển thị thanh progress bar. Nội dung thẻ <div> sẽ bị ẩn cho tới khi việc upload diễn ra. Bây giờ phía trước hàm stopUpload() bạn thêm hàm startUpload() như sau:

<script>
function startUpload(){
    document.getElementById('upload_progress').removeAttribute('class');
    return true;
}

function stopUpload(success){
...
</script>

Và trong file upload.html bạn thêm thuộc tính onsubmit vào thẻ mở của form như sau:

<form action="process_upload.php" method="post" enctype="multipart/form-data" target="iframe_upload" onsubmit="startUpload();">

Sử dụng thuộc tính onsubmit như trên thì hàm startUpload sẽ được gọi khi việc upload diễn ra.

Cuối cùng để ẩn thanh progress bar khi việc upload kết thúc bạn cần thêm một câu lệnh để gán lại thuộc tính style cho thẻ div#upload_progress vào hàm stopUpload như sau:

function stopUpload(success){
        var result = ';
        if (success == 1){
            ....
        }
        document.getElementById('upload_progress').setAttribute('style', 'display: none');
        return true;   
}

Refresh lại trang upload.html và thực hiện việc upload tập tin lại bạn sẽ thấy thanh progress bar hiển thị khi việc upload diễn ra và ẩn sau khi kết thúc. Nếu bạn kiểm tra ở trên máy local thì có thể bạn không phát hiện được sự thay đổi do quá trình xử lý upload file diễn ra nhanh. Để làm chậm quá trình upload bạn có thể thêm dòng lệnh sau vào tập tin process_upload.php

<?php
...
if(move_uploaded_file($_FILES['file_upload']['tmp_name'], $target_path)) {
    $status = 1;
}
sleep(3);
?>
0