fetch获取请求进度

作者: jie 分类: JavaScript 发布时间: 2024-12-12 11:27

fetch API 本身不直接支持请求进度的监控,但你可以通过使用 ReadableStream 和 Response.body 来间接实现下载进度的跟踪。对于上传进度,fetch 目前没有直接的方法来跟踪。

以下是一个使用 fetch 和 ReadableStream 来获取下载进度的示例:

function fetchWithProgress(url, onProgress) {
	return fetch(url).then(response => {
		if (!response.ok) {
			throw new Error(`HTTP error! status: ${response.status}`);
		}
		const contentLength = response.headers.get('Content-Length');
		if (!contentLength) {
			console.warn('Content-Length response header is missing');
		}
		const total = parseInt(contentLength, 10);
		let loaded = 0;
		const reader = response.body.getReader();
		const stream = new ReadableStream({
			start(controller) {
				function read() {
					reader.read().then(({
						done,
						value
					}) => {
						if (done) {
							controller.close();
							return;
						}
						loaded += value.length;
						if (onProgress) {
							onProgress(loaded, total);
						}
						controller.enqueue(value);
						read();
					}).catch(error => {
						console.error('Stream reading error:', error);
						controller.error(error);
					});
				}
				read();
			}
		});
		return new Response(stream, {
			headers: response.headers
		});
	});
}
// 使用示例
fetchWithProgress('https://example.com/large-file.zip', (loaded, total) => {
	console.log(`Progress: ${loaded} / ${total}`);
}).then(response => {
	return response.blob();
}).then(blob => {
	// 处理下载的 blob
}).catch(error => {
	console.error('Fetch error:', error);
});

在这个示例中,我们使用 ReadableStream 来读取响应流,并在每次读取时更新进度。onProgress 回调函数会被调用,并传入已加载的字节数和总字节数(如果可用)。这种方法适用于监控下载进度,但对于上传进度,你可能需要使用 XMLHttpRequest

function uploadFile(file) {
	const xhr = new XMLHttpRequest();
	// 监听上传进度事件  
	xhr.upload.addEventListener('progress', (event) => {
		if (event.lengthComputable) {
			const percentComplete = (event.loaded / event.total) * 100;
			console.log(`Upload progress: ${percentComplete.toFixed(2)}%`);
		}
	});
	// 监听下载进度事件  
	xhr.addEventListener('progress', (event) => {
		if (event.lengthComputable) {
			const percentComplete = (event.loaded / event.total) * 100;
			console.log(`Download progress: ${percentComplete.toFixed(2)}%`);
		}
	});
	// 请求完成时的事件  
	xhr.addEventListener('load', () => {
		if (xhr.status === 200) {
			console.log('Upload complete!');
		} else {
			console.error('Upload failed!');
		}
	});
	// 请求错误时的事件  
	xhr.addEventListener('error', () => {
		console.error('Request error!');
	});
	// 设置请求方法和目标URL  
	xhr.open('POST', 'your-upload-url-here');
	// 发送请求  
	xhr.send(file);
}

// 使用示例
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', (event) => {
	const file = event.target.files[0];
	if (file) {
		uploadFile(file);
	}
});

ReadableStream

Stream API 中的 ReadableStream接口表示可读的字节数据流。Fetch API 通过 Response的属性 body 提供了一个具体的 ReadableStream 对象。

发表回复