5.3 傳送檔案資料
若有包含檔案類型的資料
加上以下幾個參數:
contentType:若有傳送檔案,設定 false,也就是會將 header 資訊中的
Content-Type
設定成multipart/form-data
;預設是application/x-www-form-urlencoded
。processData:不用額外處理資料。例:如果是
GET
,預設會將data
物件資料字串化,放到網址。cache:避免有圖片 cache 狀況。
xhr:改寫
XMLHttpRequest
,然後回傳,主要是要監聽progress
事件。
$.ajax({
url: "https://...",
type: "POST", // 傳送資料有包含檔案,必須是 POST
data: "物件",
dataType: "json",
contentType: false, // 若有傳送檔案,設定 false,也就是將 Content-Type 設定成 multipart/form-data;預設是 application/x-www-form-urlencoded
processData: false, // 不用額外處理資料。例:如果是 GET,預設會將 data 物件資料字串化,放到網址
cache: false, // 避免有圖片 cache 狀況
xhr: function() { // 改寫 XMLHttpRequest,然後回傳
//var myXhr = $.ajaxSettings.xhr(); // jQuery 的寫法,可以取得 XMLHttpRequest 物件
let myXhr = new XMLHttpRequest(); // 取得 XMLHttpRequest 物件
if(myXhr.upload){
// 在 upload 上,綁定 progress 事件
myXhr.upload.addEventListener('progress', function(e) { // 監聽 progress 事件
if(e.lengthComputable){
progress_percent = parseInt((e.loaded / e.total) * 100);
}
});
}
return myXhr;
},
beforeSend: function(){
},
headers: {
// "X-CSRF-Token":"abcde"
},
statusCode: {
200: function (res) {
},
404: function (res) {
},
500: function (res) {
}
},
success: function(data){
console.log(data);
},
error: function(xhr){
console.log(xhr);
},
complete: function(xhr){
console.log(xhr);
}
});
jQuery 傳檔範例
完整範立:建立 ajax/practice/upload_file.html
檔案,內容如下,留意 $.ajax
的部份:
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="utf-8">
<title>AJAX: 檔案上傳進度顯示</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>
<!-- accept='image/*' -->
<input type="file" id="the_file" accept="image/*" multiple>
<ul class="picture_list"></ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
$(function(){
$("#the_file").on("change", function(e){
// 清空
$("ul.picture_list").html("");
//console.log("here");
//console.log(this);
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("here2");
//console.log(this);
// 加進節點
$("ul.picture_list").append(`
<li data-index="${i}">
<img class="preview" src="${reader.result}">
<div class="progressbar"><span class="progress" style="width: 0%;"></span></div>
</li>
`);
// 這裡實際將檔案傳送出去: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,
dataType: "json",
contentType: false,
cache: false,
processData:false,
xhr: function() {
console.log("嗨 xhr()");
let myXhr = new XMLHttpRequest();
if(myXhr.upload){
myXhr.upload.addEventListener('progress', function(evt) {
console.log("progress 事件觸發,印出事件物件:");
console.log(evt)
// evt.lengthComputable: 是否可被計算
// evt.loaded: 已傳了多少
// evt.total: 總共有多少要傳
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 + "%");
// 找到對應的進度條
$("ul.picture_list li[data-index=" + i + "]").find("span.progress").attr("style", "width: " + percent + "%;");
}
}
});
}
return myXhr;
},
success: function(data_obj) { // 從伺服器回傳的資料
console.log("success");
alert("傳送完成");
console.log(data_obj);
}
});
});
}
});
});
</script>
</body>
</html>
執行 http://127.0.0.1:5500/practice/upload_file.html
測試看看。
Last updated