微语:代码适合中午敲,早晚出BUG
Avue+vue2实现大型文件切片上传 Vue
1.Avue配置项avue-crud中需要添加文件上传前函数
<avue-crud
:upload-before="uploadBefore"
>
</avue-crud>
2.工具函数代码
// 引入axios进行http请求
import axios from "axios";
// 异步函数Fileslicing,用于处理文件的分片上传
async function Fileslicing(vueInstance, file, done, loading, column) {
let _this = vueInstance; // 将vue实例保存在_this中,用于后续引用
const CHUNK_SIZE = 1 * 1024 * 1024; // 定义每个分片的大小为1MB
// const CHUNK_SIZE = 512 * 1024; // 或定义分片大小为500KB
const totalChunks = Math.ceil(file.size / CHUNK_SIZE); // 计算总的分片数量
let uploadedChunks = 0; // 已上传分片的计数器
const overallStartTime = performance.now(); // 记录开始上传的时间
// 循环处理每个分片
for (let index = 0; index < totalChunks; index++) {
const start = index * CHUNK_SIZE; // 计算当前分片的起始位置
const end = Math.min(start + CHUNK_SIZE, file.size); // 计算结束位置,确保不超出文件大小
const blob = file.slice(start, end); // 从文件中切割出当前分片
// 创建一个新的文件对象用于上传,包含当前分片内容
const chunkFile = new File([blob], `${file.name}-${index}`, {
type: file.type,
});
const formData = new FormData(); // 使用FormData上传分片
formData.append("file", chunkFile); // 添加当前分片
formData.append("chunkNumber", index); // 当前分片的序号
formData.append("totalChunks", totalChunks); // 总分片数
formData.append("fileName", file.name); // 原文件名
try {
// 发起分片上传请求
const response = await axios.post(
"/api/blade-resource/oss/endpoint/chunk",
formData,
{
headers: {
"Content-Type": "multipart/form-data",
},
}
);
uploadedChunks++; // 上传成功后,已上传分片数+1
// 计算并显示上传进度
const progressPercentage = ((uploadedChunks / totalChunks) * 100).toFixed(2);
// 显示上传进度的通知
vueInstance.$notify.info({
title: "进度",
message: `当前上传进度: ${progressPercentage}%`,
});
if(progressPercentage == 100){
// 如果上传进度达到100%,显示文件上传完成的通知
vueInstance.$notify({
type: 'success',
title: "通知",
message: `文件已上传完成!正在处理中请稍等......`,
});
}
// 如果当前分片是最后一个分片
if (index === totalChunks - 1) {
// 发起合并文件的请求
const fileData = {
fileName: file.name,
totalChunks: totalChunks,
};
const Stresponse = await axios.post(
"/api/blade-resource/oss/endpoint/mergeFile",
fileData,
{
headers: {
"Content-Type": "application/json",
},
}
);
if (Stresponse.data.code === 200) {
// 如果文件合并成功
const overallEndTime = performance.now(); // 记录操作结束时间
// 计算总耗时
const totalFunctionTime = (overallEndTime - overallStartTime) / 1000;
column.tip = ``; // 可根据需要进行操作
let url = (Stresponse.data.data.domain + '/' + Stresponse.data.data.name);
_this.form.videoUrl = url; // 更新vue实例中的视频URL
loading(); // 可能是结束加载状态的函数
// 显示上传成功的消息
vueInstance.$message.success(
`上传成功:文件名:${file.name},文件大小${(file.size / (1024 * 1024)).toFixed(2)} MB, 上传进度: ${progressPercentage}%,总耗时:${totalFunctionTime.toFixed(2)}秒`
);
} else {
// 如果文件合并失败
loading();
vueInstance.$message.error("文件合并失败");
}
}
} catch (error) {
// 如果上传过程中出现错误
vueInstance.$message.error("上传出错");
loading(); // 结束加载状态
return; // 停止执行
}
}
}
// 导出Fileslicing函数,使其在Vue实例中可用
export default {
install(Vue) {
Vue.prototype.$fileslicing = Fileslicing;
},
};
3.注册全局,在main.js中引入
import FileslicingPlugin from '../src/util/Fileslicing';
Vue.use(FileslicingPlugin);
4.页面使用
Avue文件上传前函数
uploadBefore(file, done, loading, column) {
this.$fileslicing(this,file,done,loading,column);//文件切换全局函数(初始)
},
Vue配置API代理 Vue
vite.config.js配置如下
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig({
plugins: [
vue(), // 添加 Vue 插件配置
],
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
},
},
server: {
port: 2888,
proxy: {
'/api': {
target: 'http://192.168.3.14:13000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
})
axios封装
import axios from 'axios';
// 创建axios实例
const instance = axios.create({
timeout: 10000, // 设置超时时间为10秒
headers: {
'Content-Type': 'application/json', // 设置Content-Type
},
// 删除baseURL配置
});
// 添加请求拦截器
instance.interceptors.request.use(
config => {
// 在请求发送之前做些什么
// 如果需要在请求发送前进行额外的处理,可以在这里添加
return config;
},
error => {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加响应拦截器
instance.interceptors.response.use(
response => {
// 对响应数据做处理
return response.data;
},
error => {
// 对响应错误做处理
return Promise.reject(error);
}
);
export default instance;
API引用
import request from '@/axios';
export const $_deliveryInfo = (params) => {
return request({
url: '/api/logpm-distribution/a/abc', // 注意这里的 URL带上API 更改
method: 'get',
params
})
}
启动项目如果只有本地地址需要再package.json中配置
"scripts": {
"dev": "vite --host",
},