- 創建組件:創建一個組件用于處理文件上傳,命名為
Upload.vue
。<template><div><input type="file" @change="handleFileChange" /><button @click="startUpload">開始上傳</button></div> </template><script setup lang="ts"> import { ref } from 'vue'; import { ElMessage } from 'element-plus';const file = ref<File | null>(null);const handleFileChange = (event: Event) => {const target = event.target as HTMLInputElement;if (target.files?.length) {file.value = target.files[0];} };const startUpload = () => {if (!file.value) {ElMessage.error('請選擇文件');return;}// 在這里編寫文件切片上傳邏輯 }; </script>
- 添加切片邏輯:在
startUpload
方法中,我們需要將選擇的文件切成多個小塊進行上傳。可以使用FileReader
進行文件切片操作。
const startUpload = () => {if (!file.value) {ElMessage.error('請選擇文件');return;}const chunkSize = 1024 * 1024; // 每個切片大小,這里設置為1MBconst totalChunks = Math.ceil(file.value.size / chunkSize); // 總切片數for (let i = 0; i < totalChunks; i++) {const start = i * chunkSize;const end = Math.min(start + chunkSize, file.value.size);const chunk = file.value.slice(start, end);// 在這里將切片上傳到服務器}
};
3.切片上傳到服務器:可以使用axios
庫進行文件上傳操作。
import axios from 'axios';const startUpload = async () => {if (!file.value) {ElMessage.error('請選擇文件');return;}const chunkSize = 1024 * 1024; // 每個切片大小,這里設置為1MBconst totalChunks = Math.ceil(file.value.size / chunkSize); // 總切片數for (let i = 0; i < totalChunks; i++) {const start = i * chunkSize;const end = Math.min(start + chunkSize, file.value.size);const chunk = file.value.slice(start, end);const formData = new FormData();formData.append('chunk', chunk);try {await axios.post('/upload', formData);// 上傳成功的處理邏輯} catch (error) {// 上傳失敗的處理邏輯}}
};
4.添加進度條:可以使用Element Plus的ElProgress
組件顯示上傳進度。
<template><div><input type="file" @change="handleFileChange" /><el-progress v-if="progressVisible" :percentage="uploadPercentage" /><button @click="startUpload">開始上傳</button></div>
</template><script setup lang="ts">
import { ref, reactive } from 'vue';
import axios from 'axios';
import { ElMessage, ElProgress } from 'element-plus';const file = ref<File | null>(null);
const progress = reactive({visible: false,percentage: 0,
});const handleFileChange = (event: Event) => {const target = event.target as HTMLInputElement;if (target.files?.length) {file.value = target.files[0];}
};const startUpload = async () => {if (!file.value) {ElMessage.error('請選擇文件');return;}const chunkSize = 1024 * 1024; // 每個切片大小,這里設置為1MBconst totalChunks = Math.ceil(file.value.size / chunkSize); // 總切片數progress.visible = true;progress.percentage = 0;for (let i = 0; i < totalChunks; i++) {const start = i * chunkSize;const end = Math.min(start + chunkSize, file.value.size);const chunk = file.value.slice(start, end);const formData = new FormData();formData.append('chunk', chunk);try {await axios.post('/upload', formData, {onUploadProgress: (progressEvent: ProgressEvent) => {const percentage = Math.round((progressEvent.loaded / progressEvent.total) * 100);progress.percentage = percentage;},});// 上傳成功的處理邏輯} catch (error) {// 上傳失敗的處理邏輯}}progress.visible = false;
};
</script>