6.2 參考:jquery ajax 上傳檔案並顯示進度條
目的
檔案在上傳時,前端的頁面顯示上傳的進度。這裡會用到 ajax 的技術,故此例僅提供給同學未來參考。
為了方便觀察:可將網速調慢
現在網路都滿快的,所以如果檔案太小,有時不會那麼明顯,因為會直接變成是進度 100%
。
那麼為了方便觀察,可透過以下方式,將網路速度調慢。
步驟:開啟開發者工具 → Network → No throttling → Fast 3G。(測完之後,記得調回原來的)
ajax 傳送檔案
結果示意
進度條的 CodePen 參考:https://codepen.io/carlos411/pen/QWPyzVW
建立 html5/file/file2_upload.html
檔案,內容如下:
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="utf-8">
<title>File API:檔案上傳進度顯示</title>
<style>
img.preview{
width: 200px;
}
ul{
list-style: none;
margin: 0;
padding: 0;
}
ul > li{
display: inline-block;
vertical-align: top;
}
div.progressbar{
height: 20px;
background-color: #e9ecef;
border-radius: 8px;
position: relative;
overflow: hidden;
margin-bottom: 30px;
}
div.progressbar > span.progress{
position: absolute;
top: 0;
left: 0;
height: 100%;
box-sizing: border-box;
background-color: #007bff;
}
</style>
</head>
<body>
<input type="file" id="the_file" accept="image/*" multiple>
<ul class="picture_list"></ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script>
var the_file_element = document.getElementById("the_file");
the_file_element.addEventListener("change", function(e){
var picture_list = document.getElementsByClassName("picture_list")[0];
picture_list.innerHTML = ""; // 清空
var that = this; // 將 this 用 that 來替代,底下程式會用到
// 跑每個使用者選的檔案
for (let i = 0; i < this.files.length; i++) {
let reader = new FileReader(); // 用來讀取檔案
reader.readAsDataURL(this.files[i]); // 讀取檔案
reader.addEventListener("load", function (e) {
console.log("load 事件");
console.log(e);
// 建立 li 標籤,加上屬性、圖片、進度條,最後放入 ul 標籤裡
let li_html = `
<li data-index="${i}">
<img class="preview" src="${reader.result}">
<div class="progressbar"><span class="progress" style="width: 0%;"></span></div>
</li>
`;
picture_list.insertAdjacentHTML("beforeend", li_html); // 加進節點
// 這裡實際將檔案傳送出去:ajax 技術
});
}
});
</script>
</body>
</html>
使用 jQuery ajax 傳送檔案
在上述程式碼當中,有個註解是「// 這裡實際將檔案傳送出去:ajax 技術
」,在其底下加入以下程式碼即可:
// 這裡實際將檔案傳送出去:ajax 技術
let form_data = new FormData();
form_data.append('the_file', that.files[i]);
$.ajax({
url: "https://notes.webmix.cc/html5_tutorial/file/file_receive.php",
type: "POST",
data: form_data,
contentType: false,
cache: false,
processData:false,
xhr: function() {
//console.log("這是第幾個索引:" + i);
var myXhr = $.ajaxSettings.xhr();
if(myXhr.upload){
myXhr.upload.addEventListener('progress', function(evt) {
console.log("progress 事件觸發");
var progress_el = document.querySelector('.picture_list li[data-index="' + i + '"] span.progress');
if (evt.lengthComputable) {
var loaded = (evt.loaded / evt.total);
if (loaded <= 1) {
//console.log(evt.loaded / evt.total)
var percent = loaded * 100;
console.log("進度:" + percent + "%");
// 改變介面進度條的百分比
progress_el.setAttribute("style", "width: " + percent + "%;");
}
}
}, false);
}
return myXhr;
},
success: function(data_obj) { // 從伺服器回傳的資料
//console.log("success");
alert("傳送完成");
console.log(data_obj);
}
});
evt.lengthComputable
:檔案大小是否可被計算。會回傳true
或false
。evt.loaded
:檔案已傳多少。evt.total
:要傳的總大小是多少。
參考:後端 PHP 程式碼接收檔案
<?php
// 傳送出去的編碼,設定為 utf-8
header('Content-Type: text/html; charset=utf-8');
// 顯示錯誤資訊
ini_set("display_errors", "On");
error_reporting(E_ALL & ~E_NOTICE);
// 取得上傳檔案的副檔名
$new_array = explode(".", $_FILES['the_file']['name']);
$ext = end($new_array);
$target_dir = "./upload/"; // 存檔的相對路徑
$new_filename = time() . "_" . rand(10,100) . "." . $ext; // 新的檔名
$target_file = $target_dir . $new_filename; // 存的位置 + 檔名
move_uploaded_file($_FILES["the_file"]["tmp_name"], $target_file); // 檔案真的存下來
// 回傳資料給前端
$arr = array('code' => "success");
echo json_encode($arr);
Last updated