base 64 分片上传文件
<template><div><input type="file" @change="onFileSelected" /><button v-if="file && !isUploading" @click="startUpload">开始上传</button><button v-if="isUploading" @click="pauseUpload">暂停上传</button><button v-if="isUploading" @click="resumeUpload">继续上传</button><p>已上传分片: {{ uploadedChunks }} / {{ totalChunks }}</p><progress :value="uploadedChunks" :max="totalChunks"></progress></div>
</template><script setup>
const file = ref(null);
const isUploading = ref(false);
const uploadedChunks = ref(0);
const totalChunks = ref(0);const chunkSize = 10 * 1024 * 1024; // 分片大小:1MB
let currentChunkIndex = 0;function onFileSelected(event) {file.value = event.target.files[0];if (file.value) {totalChunks.value = Math.ceil(file.value.size / chunkSize);}
}async function startUpload() {isUploading.value = true;await readAndUploadFileInChunks(file.value, chunkSize);isUploading.value = false;alert('文件上传完成!');
}function pauseUpload() {isUploading.value = false;
}function resumeUpload() {isUploading.value = true;// 实现暂停/继续逻辑,这里假设简单地重新开始上传startUpload();
}async function readAndUploadFileInChunks(file, chunkSize) {const fileReader = new FileReader();let offset = 0;while (offset < file.size) {const slice = file.slice(offset, offset + chunkSize);fileReader.readAsDataURL(slice); // 使用readAsDataURL读取Base64编码await new Promise((resolve) => {fileReader.onload = () => {const base64Data = fileReader.result;uploadBase64Chunk(base64Data, currentChunkIndex++);resolve();};});offset += chunkSize;}
}async function uploadBase64Chunk(base64Data, index) {try {const response = await fetch('/api/upload-base64-chunk', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({ base64Data, index }),});if (!response.ok) {throw new Error(`Failed to upload chunk ${index}: ${response.status}`);}uploadedChunks.value = index + 1;} catch (error) {console.error('Error uploading chunk:', error);// 处理错误,可能需要重新上传或提示用户}
}onMounted(() => {// 在组件挂载时注册相关事件
});onBeforeUnmount(() => {// 在组件卸载时清理资源
});// return {
// file,
// isUploading,
// uploadedChunks,
// totalChunks,
// onFileSelected,
// startUpload,
// pauseUpload,
// resumeUpload,
// };
</script>
文件流分片上传
<template><div><input type="file" @change="onFileSelected" /><button v-if="file && !isUploading" @click="startUpload">开始上传</button><button v-if="isUploading" @click="pauseUpload">暂停上传</button><button v-if="isUploading" @click="resumeUpload">继续上传</button><p>已上传分片: {{ uploadedChunks }} / {{ totalChunks }}</p><progress :value="uploadedChunks" :max="totalChunks"></progress></div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';const file = ref(null);
const isUploading = ref(false);
const uploadedChunks = ref(0);
const totalChunks = ref(0);const chunkSize = 10 * 1024 * 1024; // 分片大小:10MB
let worker = null;
let uploadQueue = [];
let currentChunkIndex = 0;function onFileSelected(event) {file.value = event.target.files[0];if (file.value) {totalChunks.value = Math.ceil(file.value.size / chunkSize);}
}async function startUpload() {isUploading.value = true;worker = new Worker('file-slicer-worker.js');worker.postMessage({ file: file.value, chunkSize });worker.onmessage = ({ data }) => {if (data.type === 'slice') {uploadQueue.push(data.chunk);uploadNextChunk();}};
}function pauseUpload() {isUploading.value = false;
}function resumeUpload() {isUploading.value = true;uploadNextChunk();
}async function uploadNextChunk() {if (!isUploading.value || currentChunkIndex >= totalChunks.value) return;const chunk = uploadQueue.shift();await uploadChunk(chunk, currentChunkIndex++);uploadedChunks.value = currentChunkIndex;if (currentChunkIndex < totalChunks.value) {uploadNextChunk();} else {// 全部上传完毕,清理资源worker.terminate();worker = null;uploadQueue = [];isUploading.value = false;alert('文件上传完成!');}
}async function uploadChunk(chunk, index) {const formData = new FormData();formData.append('file', new Blob([chunk]), `file_part_${index}`);try {const response = await fetch('/api/upload-chunk', {method: 'POST',body: formData,});if (!response.ok) {throw new Error(`Failed to upload chunk ${index}: ${response.status}`);}} catch (error) {console.error('Error uploading chunk:', error);// 处理错误,可能需要重新放入队列或提示用户}
}onMounted(() => {// 在组件挂载时注册worker相关事件
});onBeforeUnmount(() => {// 在组件卸载时清理worker资源if (worker) {worker.terminate();}
});// return {
// file,
// isUploading,
// uploadedChunks,
// totalChunks,
// onFileSelected,
// startUpload,
// pauseUpload,
// resumeUpload,
// };
</script>