Một giải pháp khả thi là sử dụng hàm new Request()
tạo sau đó kiểm tra Request.bodyUsed
Boolean
thuộc tính
Các bodyUsed
getter của thuộc tính phải trả về true nếu disturbed
, và sai khác.
để xác định xem luồng có distributed
Một đối tượng thực hiện Body
mixin được cho là disturbed
if
body
không phải là null và nó stream
là disturbed
.
Trả về fetch()
Promise
từ bên trong .then()
chuỗi để .read()
gọi đệ quy của một ReadableStream
khi Request.bodyUsed
bằng true
.
Lưu ý, phương pháp này không đọc các byte Request.body
khi các byte được truyền trực tiếp đến điểm cuối. Ngoài ra, quá trình tải lên có thể hoàn thành tốt trước khi bất kỳ phản hồi nào được trả lại đầy đủ cho trình duyệt.
const [input, progress, label] = [
document.querySelector("input")
, document.querySelector("progress")
, document.querySelector("label")
];
const url = "/path/to/server/";
input.onmousedown = () => {
label.innerHTML = "";
progress.value = "0"
};
input.onchange = (event) => {
const file = event.target.files[0];
const filename = file.name;
progress.max = file.size;
const request = new Request(url, {
method: "POST",
body: file,
cache: "no-store"
});
const upload = settings => fetch(settings);
const uploadProgress = new ReadableStream({
start(controller) {
console.log("starting upload, request.bodyUsed:", request.bodyUsed);
controller.enqueue(request.bodyUsed);
},
pull(controller) {
if (request.bodyUsed) {
controller.close();
}
controller.enqueue(request.bodyUsed);
console.log("pull, request.bodyUsed:", request.bodyUsed);
},
cancel(reason) {
console.log(reason);
}
});
const [fileUpload, reader] = [
upload(request)
.catch(e => {
reader.cancel();
throw e
})
, uploadProgress.getReader()
];
const processUploadRequest = ({value, done}) => {
if (value || done) {
console.log("upload complete, request.bodyUsed:", request.bodyUsed);
// set `progress.value` to `progress.max` here
// if not awaiting server response
// progress.value = progress.max;
return reader.closed.then(() => fileUpload);
}
console.log("upload progress:", value);
progress.value = +progress.value + 1;
return reader.read().then(result => processUploadRequest(result));
};
reader.read().then(({value, done}) => processUploadRequest({value,done}))
.then(response => response.text())
.then(text => {
console.log("response:", text);
progress.value = progress.max;
input.value = "";
})
.catch(err => console.log("upload error:", err));
}