file分片上传 方法一
bash
<template>
<input type="file" @change="handleFileChange" />
</template>
<script setup>
import { ref } from 'vue';
import axios from 'axios';
const handleFileChange = async (event) => {
const file = event.target.files[0];
if (!file) return;
const chunkSize = 1 * 1024 * 1024; // 每个分片的大小,这里以1MB为例
const chunkCount = Math.ceil(file.size / chunkSize);
for (let i = 0; i < chunkCount; i++) {
const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize);
const formData = new FormData();
formData.append('file', chunk);
// 你可能还需要其他参数,比如文件名、分片总数等
formData.append('传参', i + 1); //...
try {
const response = await axios.post('http://192.168.1.45:8086/pic/upload1', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
// 其他配置,如上传进度处理等
});
console.log(response.data);
} catch (error) {
console.error(error);
}
}
};
</script>
file分片上传 方法二
bash
<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();
}
});
</script>
base 64 分片上传文件
```bash
<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(() => {
// 在组件卸载时清理资源
});
</script>